Introduction

Suicide is the deliberate act of ending one’s own life, often stemming from various mental disorders such as depression, bipolar disorder, autism, schizophrenia, and personality disorders, as well as external stressors like financial struggles, academic pressures, relationship issues, or experiences of harassment and bullying. Factors like substance abuse, including alcoholism and benzodiazepine use, also contribute to this tragic outcome. Previous suicide attempts significantly elevate the risk of future attempts. Efforts to prevent suicide involve a multifaceted approach, including restricting access to common methods like firearms, drugs, and poisons, addressing mental health issues and substance abuse, responsible media reporting on suicides, and fostering better economic conditions. Despite the widespread availability of crisis hotlines, their effectiveness remains inadequately researched. The prevalence and methods of suicide vary across countries, often influenced by the accessibility of lethal means. Hanging, pesticide ingestion, poisoning, and firearms are among the most commonly used methods. Globally, suicides claim over 700,000 lives annually, ranking suicide as the 10th leading cause of death worldwide. Approximately 1.5% of people die by suicide, translating to roughly 12 per 100,000 individuals each year. Men are more likely to die by suicide than women, with rates ranging from 1.5 times higher in developing countries to 3.5 times higher in developed ones. Financial strain often exacerbates the risk of suicide. [1]

Research Question

Suicide is not confined to high-income countries; it is a global issue affecting all regions. Surprisingly, over 77% of suicides occur in low- and middle-income countries. However, high-income countries exhibit the highest age-standardized suicide rates. In ongoing research across 19 countries, we explore correlations between GDP, bankruptcy rates, happiness levels, and suicide rates. Understanding these intricate relationships is pivotal for policymakers, researchers, and stakeholders to devise effective interventions promoting mental well-being and economic resilience. Leveraging multidimensional datasets and advanced analytical methods, our project aims to illuminate these connections for the betterment of societies worldwide.

Data Wrangling

# Load libraries
library(dplyr)
library(readr)
library(tidyr)
library(lubridate)
library(ggplot2)
library(stringr)
library(readxl)
library(httr)

Exploration of the Bankruptcies Dataset


# Load dataset
bankruptcies <- read_csv("https://raw.githubusercontent.com/Alexburk93/Data_Wrangling_EDA/main/data/raw_data/Bankruptcies_2011-2020.csv")
New names:Rows: 987 Columns: 19── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (13): COU, Country, VAR, Variable, MEA, Measure, ISIC4...7, ISIC4...8, TIME, Time, Unit Code, Unit, PowerCode
dbl  (2): PowerCode Code, Value
lgl  (4): Reference Period Code, Reference Period, Flag Codes, Flags
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Display structure of dataset
str(bankruptcies)
spc_tbl_ [987 × 19] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ COU                  : chr [1:987] "CAN" "CAN" "CAN" "CAN" ...
 $ Country              : chr [1:987] "Canada" "Canada" "Canada" "Canada" ...
 $ VAR                  : chr [1:987] "BANKRUPTCIES" "BANKRUPTCIES" "BANKRUPTCIES" "BANKRUPTCIES" ...
 $ Variable             : chr [1:987] "Number of bankruptcies" "Number of bankruptcies" "Number of bankruptcies" "Number of bankruptcies" ...
 $ MEA                  : chr [1:987] "INDEX" "INDEX" "INDEX" "INDEX" ...
 $ Measure              : chr [1:987] "Index 2007=100" "Index 2007=100" "Index 2007=100" "Index 2007=100" ...
 $ ISIC4...7            : chr [1:987] "01_99" "01_99" "01_99" "01_99" ...
 $ ISIC4...8            : chr [1:987] "Grand Total" "Grand Total" "Grand Total" "Grand Total" ...
 $ TIME                 : chr [1:987] "2011-Q1" "2011-Q2" "2011-Q3" "2011-Q4" ...
 $ Time                 : chr [1:987] "Q1-2011" "Q2-2011" "Q3-2011" "Q4-2011" ...
 $ Unit Code            : chr [1:987] "IDX" "IDX" "IDX" "IDX" ...
 $ Unit                 : chr [1:987] "Index" "Index" "Index" "Index" ...
 $ PowerCode Code       : num [1:987] 0 0 0 0 0 0 0 0 0 0 ...
 $ PowerCode            : chr [1:987] "Units" "Units" "Units" "Units" ...
 $ Reference Period Code: logi [1:987] NA NA NA NA NA NA ...
 $ Reference Period     : logi [1:987] NA NA NA NA NA NA ...
 $ Value                : num [1:987] 60 58.3 56.3 55.3 54 ...
 $ Flag Codes           : logi [1:987] NA NA NA NA NA NA ...
 $ Flags                : logi [1:987] NA NA NA NA NA NA ...
 - attr(*, "spec")=
  .. cols(
  ..   COU = col_character(),
  ..   Country = col_character(),
  ..   VAR = col_character(),
  ..   Variable = col_character(),
  ..   MEA = col_character(),
  ..   Measure = col_character(),
  ..   ISIC4...7 = col_character(),
  ..   ISIC4...8 = col_character(),
  ..   TIME = col_character(),
  ..   Time = col_character(),
  ..   `Unit Code` = col_character(),
  ..   Unit = col_character(),
  ..   `PowerCode Code` = col_double(),
  ..   PowerCode = col_character(),
  ..   `Reference Period Code` = col_logical(),
  ..   `Reference Period` = col_logical(),
  ..   Value = col_double(),
  ..   `Flag Codes` = col_logical(),
  ..   Flags = col_logical()
  .. )
 - attr(*, "problems")=<externalptr> 
# Show the first few rows 
head(bankruptcies)

# Summary statistics of numerical attributes
summary(bankruptcies)
     COU              Country              VAR              Variable             MEA              Measure         
 Length:987         Length:987         Length:987         Length:987         Length:987         Length:987        
 Class :character   Class :character   Class :character   Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character   Mode  :character   Mode  :character  
                                                                                                                  
                                                                                                                  
                                                                                                                  
  ISIC4...7          ISIC4...8             TIME               Time            Unit Code             Unit          
 Length:987         Length:987         Length:987         Length:987         Length:987         Length:987        
 Class :character   Class :character   Class :character   Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character   Mode  :character   Mode  :character  
                                                                                                                  
                                                                                                                  
                                                                                                                  
 PowerCode Code  PowerCode         Reference Period Code Reference Period     Value        Flag Codes    
 Min.   :0      Length:987         Mode:logical          Mode:logical     Min.   : 32.09   Mode:logical  
 1st Qu.:0      Class :character   NA's:987              NA's:987         1st Qu.: 97.05   NA's:987      
 Median :0      Mode  :character                                          Median :121.18                 
 Mean   :0                                                                Mean   :139.36                 
 3rd Qu.:0                                                                3rd Qu.:146.24                 
 Max.   :0                                                                Max.   :949.42                 
  Flags        
 Mode:logical  
 NA's:987      
               
               
               
               
# Summary statistics of categorical attribute
table(bankruptcies$Country)

     Australia        Belgium         Brazil         Canada        Denmark        Finland         France 
            41             82             36             40             40             80             40 
       Germany        Iceland          Italy          Japan    Netherlands    New Zealand         Norway 
            80             40             40             40             80             28             80 
  South Africa          Spain         Sweden United Kingdom  United States 
            38             40             82             40             40 
# Check for missing values
sum(is.na(bankruptcies))
[1] 3948
# Removing NA's columns and Time (Duplicate)  
data <- select(bankruptcies, -`Flag Codes`, -Flags, -`Reference Period Code`, -`Reference Period`, -TIME)
data %>% 
  sample_n(10)

# Display the structure of the modified dataset
str(data)
tibble [987 × 14] (S3: tbl_df/tbl/data.frame)
 $ COU           : chr [1:987] "CAN" "CAN" "CAN" "CAN" ...
 $ Country       : chr [1:987] "Canada" "Canada" "Canada" "Canada" ...
 $ VAR           : chr [1:987] "BANKRUPTCIES" "BANKRUPTCIES" "BANKRUPTCIES" "BANKRUPTCIES" ...
 $ Variable      : chr [1:987] "Number of bankruptcies" "Number of bankruptcies" "Number of bankruptcies" "Number of bankruptcies" ...
 $ MEA           : chr [1:987] "INDEX" "INDEX" "INDEX" "INDEX" ...
 $ Measure       : chr [1:987] "Index 2007=100" "Index 2007=100" "Index 2007=100" "Index 2007=100" ...
 $ ISIC4...7     : chr [1:987] "01_99" "01_99" "01_99" "01_99" ...
 $ ISIC4...8     : chr [1:987] "Grand Total" "Grand Total" "Grand Total" "Grand Total" ...
 $ Time          : chr [1:987] "Q1-2011" "Q2-2011" "Q3-2011" "Q4-2011" ...
 $ Unit Code     : chr [1:987] "IDX" "IDX" "IDX" "IDX" ...
 $ Unit          : chr [1:987] "Index" "Index" "Index" "Index" ...
 $ PowerCode Code: num [1:987] 0 0 0 0 0 0 0 0 0 0 ...
 $ PowerCode     : chr [1:987] "Units" "Units" "Units" "Units" ...
 $ Value         : num [1:987] 60 58.3 56.3 55.3 54 ...
# Check the dimension of data
dim(data)
[1] 987  14

For this project, we are only focusing on information from 2011 to 2020. And to minimize the workload, we are analyzing 19 countries.

# Create new columns 'Quarter' and 'Year' from 'Time'
new_data <- mutate(data,
                   Quarter = str_sub(Time, 1, 2), # Extract Quarter
                   Year = as.numeric(str_sub(Time, 4))) # Extract Year and convert to numeric

# remove the original 'Time' column
new_data <- select(new_data, -Time)  
new_data

# Get date range
date_range <- range(new_data$Year)

# Count unique countries
n_countries <- length(unique(new_data$Country))

# Print the results
n_countries
[1] 19
date_range
[1] 2011 2021
# Only need data from 2011-2020, excluding 2021
bankruptcy_data <- filter(new_data, Year != 2021)
new_data

# Get date range of new updated dataset
date_range <- range(bankruptcy_data$Year)

# Extract start and end years from the range
start_year <- date_range[1]
end_year <- date_range[2]

# Count unique countries
n_countries <- length(unique(bankruptcy_data$Country))

# Print the results
cat("Number of country: ", n_countries, "\n") 
Number of country:  19 
cat("Date range from: ", start_year, " to ", end_year, "\n")
Date range from:  2011  to  2020 

Exploring GDP dataset & analyze foundings

# Load dataset 
my_data <- read_csv("https://raw.githubusercontent.com/Alexburk93/Data_Wrangling_EDA/main/data/raw_data/GDP_Data/GDP_capita_1960_2022.csv")
Rows: 266 Columns: 10── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): Country Name
dbl (9): 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
my_data

The Years are in the header, using pivot_longer() to convert into two column Year and GDP

# Pivot the data from wide to long format
joy <- pivot_longer(my_data, 
                         cols = -c(`Country Name`),
                         names_to = "Year", 
                         values_to = "GDP")

# Show the first few rows

Perfom summary stastics, check for NA's, dimension dim(), etc.

# Display structure of dataset
str(joy)
tibble [2,394 × 3] (S3: tbl_df/tbl/data.frame)
 $ Country Name: chr [1:2394] "Aruba" "Aruba" "Aruba" "Aruba" ...
 $ Year        : chr [1:2394] "2011" "2012" "2013" "2014" ...
 $ GDP         : num [1:2394] 26043 25611 26515 26940 28419 ...
# Show the first few rows 
head(joy)

# Summary statistics of numerical attributes
summary(joy)
 Country Name           Year                GDP        
 Length:2394        Length:2394        Min.   :   217  
 Class :character   Class :character   1st Qu.:  2099  
 Mode  :character   Mode  :character   Median :  6570  
                                       Mean   : 16591  
                                       3rd Qu.: 19866  
                                       Max.   :199383  
                                       NA's   :66      
# Summary statistics of categorical attribute
table(joy$`Indicator Code`)
Warning: Unknown or uninitialised column: `Indicator Code`.
< table of extent 0 >
# Check for missing values
sum(is.na(joy))
[1] 66
# Check the dimension of data
dim(joy)
[1] 2394    3

Filter the data to only show the 19 countries and the date range the project is focused on.

# Define the list of 19 countries
countries_of_interest <- c("Australia", "Belgium", "Brazil", "Canada", "Denmark",
                           "Finland", "France", "Germany", "Iceland", "Italy",
                           "Japan", "Netherlands", "New Zealand", "Norway", 
                           "South Africa", "Spain", "Sweden", "United Kingdom", 
                           "United States")

# Filter the data for the 19 countries
gdp <- joy %>%
  filter(`Country Name` %in% countries_of_interest)

# Define the date range of focus
start_year <- 2011
end_year <- 2020

# Filter the data for the date range
gdp <- gdp %>%
  filter(as.numeric(Year) >= start_year & as.numeric(Year) <= end_year)

# Show the filtered data
gdp %>% 
  sample_n(10)
# Display structure of dataset
str(gdp)
tibble [171 × 3] (S3: tbl_df/tbl/data.frame)
 $ Country Name: chr [1:171] "Australia" "Australia" "Australia" "Australia" ...
 $ Year        : chr [1:171] "2011" "2012" "2013" "2014" ...
 $ GDP         : num [1:171] 62610 68078 68198 62558 56759 ...
# Convert Year to numeric 
# gdp$Year <- as.numeric(gdp$Year)

# Show the first few rows 
head(gdp)

# Summary statistics of numerical attributes
summary(gdp)
 Country Name           Year                GDP        
 Length:171         Length:171         Min.   :  5735  
 Class :character   Class :character   1st Qu.: 38808  
 Mode  :character   Mode  :character   Median : 46299  
                                       Mean   : 45324  
                                       3rd Qu.: 53541  
                                       Max.   :103554  
# Summary statistics of categorical attribute
table(gdp$`Indicator Code`)
Warning: Unknown or uninitialised column: `Indicator Code`.
< table of extent 0 >
# Check for missing values
sum(is.na(gdp))
[1] 0
# Check the dimension of data
dim(gdp)
[1] 171   3
# Group the filtered data by Year and calculate the mean GDP for each year
mean_gdp_by_year <- gdp %>%
  group_by(Year) %>%
  summarize(mean_GDP = mean(GDP, na.rm = TRUE))

# Show the mean GDP for each year
print(mean_gdp_by_year)

Visualization for top 10 highest GDP by Counries Over Time.

# Filter to include only the top 10 countries with the highest GDP values
top_10_gdp <- gdp %>%
  group_by(`Country Name`) %>%
  summarize(total_gdp = sum(GDP, na.rm = TRUE)) %>%
  top_n(10, total_gdp) %>%
  left_join(gdp, by = "Country Name")

# Convert GDP values to millions or billions
top_10_gdp <- top_10_gdp %>%
  mutate(GDP_formatted = case_when(
    GDP >= 1e12 ~ paste0(round(GDP / 1e12, 1), "T"),  # Convert to trillions
    GDP >= 1e9 ~ paste0(round(GDP / 1e9, 1), "B"),  # Convert to billions
    GDP >= 1e6 ~ paste0(round(GDP / 1e6, 1), "M"),   # Convert to millions
    TRUE ~ as.character(GDP)                        # Keep unchanged if less than 1 million
  ))

# Create a line plot of GDP over time with formatted values for the top 10 countries
ggplot(top_10_gdp, aes(x = Year, y = GDP, group = `Country Name`)) +
  geom_line(aes(color = `Country Name`)) +
  labs(title = "GDP Trends Over Time (Top 10 Countries)",
       x = "Year",
       y = "GDP",
       color = "Country") +
  scale_y_continuous(labels = function(x) paste0(x, "")) +  # Ensure y-axis labels are character type
  theme_minimal()

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.

Exploration of the Suicide Rate Dataset

# Load data set from github
suicide_df = read_csv("https://raw.githubusercontent.com/Alexburk93/Data_Wrangling_EDA/main/data/raw_data/death-rate-from-suicides-gho%20new.csv")
Rows: 3876 Columns: 4── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Entity, Code, Age-standardized suicide rate - Sex: both sexes
dbl (1): Year
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
suicide_df$`Age-standardized suicide rate - Sex: both sexes` = as.double(suicide_df$`Age-standardized suicide rate - Sex: both sexes`)
Warning: NAs introduced by coercion
summary(suicide_df)
    Entity              Code                Year      Age-standardized suicide rate - Sex: both sexes
 Length:3876        Length:3876        Min.   :2000   Min.   :  0.000                                
 Class :character   Class :character   1st Qu.:2004   1st Qu.:  5.955                                
 Mode  :character   Mode  :character   Median :2009   Median : 10.015                                
                                       Mean   :2009   Mean   : 68.421                                
                                       3rd Qu.:2014   3rd Qu.:141.230                                
                                       Max.   :2019   Max.   :962.889                                
                                                      NA's   :5                                      
# Consider removing Lesotho from the analysis 
suicide_df %>% 
  filter(is.na(`Age-standardized suicide rate - Sex: both sexes`))
# Remove the Region / Income classes and Lesotho
suicide_df_countries = suicide_df %>% 
  filter(Code != "0", Code != "LSO")
avg_country = suicide_df_countries %>% 
  group_by(Entity) %>% 
  summarise(avg_per_country = mean(`Age-standardized suicide rate - Sex: both sexes`)) %>% 
  arrange(desc(avg_per_country))
ggplot(avg_country, aes(x = avg_per_country)) +
  geom_histogram() +
  labs(x = "Mean Suicide rate", y = "Frequency", title = "Distribution of mean of suicide rate") +
  theme_minimal()

Exploration of the Happiness Dataset

# Use the raw file URL
url <- "https://github.com/Alexburk93/Data_Wrangling_EDA/raw/main/data/raw_data/WHR20_DataForTable2.1.xls"
response <- GET(url)
content <- content(response, "raw")
temp <- tempfile(fileext = ".xls")
writeBin(content, temp)
happiness_df <- read_excel(temp)

# View the data
head(happiness_df)
NA
# create data frame with selected columns. Based on the description of the different variables.
happiness_df_filtered = happiness_df %>% 
  select(`Country name`, `year` , `Life Ladder`, `Social support`, `Healthy life expectancy at birth`, `Freedom to make life choices`, `Perceptions of corruption`)

summary(happiness_df_filtered)
 Country name            year       Life Ladder    Social support   Healthy life expectancy at birth
 Length:1848        Min.   :2005   Min.   :2.375   Min.   :0.2902   Min.   :32.30                   
 Class :character   1st Qu.:2010   1st Qu.:4.623   1st Qu.:0.7483   1st Qu.:58.30                   
 Mode  :character   Median :2013   Median :5.363   Median :0.8340   Median :65.10                   
                    Mean   :2013   Mean   :5.446   Mean   :0.8111   Mean   :63.17                   
                    3rd Qu.:2016   3rd Qu.:6.268   3rd Qu.:0.9046   3rd Qu.:68.39                   
                    Max.   :2019   Max.   :8.019   Max.   :0.9873   Max.   :77.10                   
                                                   NA's   :13       NA's   :52                      
 Freedom to make life choices Perceptions of corruption
 Min.   :0.2575               Min.   :0.0352           
 1st Qu.:0.6431               1st Qu.:0.6927           
 Median :0.7575               Median :0.8036           
 Mean   :0.7385               Mean   :0.7491           
 3rd Qu.:0.8524               3rd Qu.:0.8737           
 Max.   :0.9852               Max.   :0.9833           
 NA's   :31                   NA's   :103              
avg_happiness_per_country = happiness_df_filtered %>% 
  group_by(`Country name`) %>% 
  summarise(avg_happiness = mean(`Life Ladder`)) %>% 
  arrange(desc(avg_happiness))
ggplot(avg_happiness_per_country, aes(x = avg_happiness)) +
  geom_histogram() +
  labs(x = "Mean Happiness Level", y = "Frequency", title = "Distribution of mean of happiness rate") +
  theme_minimal()

Data for Final Presentation

Happiness Data for the 19 countries of interest from 2011 - 2019

# Define the list of 19 countries
countries_of_interest <- c("Australia", "Belgium", "Brazil", "Canada", "Denmark",
                           "Finland", "France", "Germany", "Iceland", "Italy",
                           "Japan", "Netherlands", "New Zealand", "Norway", 
                           "South Africa", "Spain", "Sweden", "United Kingdom", 
                           "United States")

# Filter the data for the 19 countries
happiness_new<- happiness_df_filtered %>%
  filter(`Country name` %in% countries_of_interest)

# Define the date range of focus
start_year <- 2011
end_year <- 2020

# Filter the data for the date range
happiness_data <- happiness_new %>%
  filter(as.numeric(year) >= start_year & as.numeric(year) <= end_year)

# Show the filtered data
happiness_data %>% 
  sample_n(10)
# Check if all countries of interest are present in the filtered data
missing_countries <- setdiff(countries_of_interest, unique(happiness_data$`Country name`))

# Print the missing countries, if any
if(length(missing_countries) > 0) {
  print("The following countries are missing from the filtered data:")
  print(missing_countries)
} else {
  print("All countries of interest are selected from the filtered data.")
}
[1] "All countries of interest are selected from the filtered data."
# Count the occurrences of each country in the filtered data
country_counts <- table(happiness_data$`Country name`)

# Print the country names and their counts
print("Country Name\t\tCount")
[1] "Country Name\t\tCount"
for (country in names(country_counts)) {
  cat(country, "\t\t\t", country_counts[country], "\n")
}
Australia            9 
Belgium              9 
Brazil           9 
Canada           9 
Denmark              9 
Finland              9 
France           9 
Germany              9 
Iceland              6 
Italy            9 
Japan            9 
Netherlands              9 
New Zealand              9 
Norway           7 
South Africa             9 
Spain            9 
Sweden           9 
United Kingdom           9 
United States            9 

Suicide Data for the 19 countries of interest from 2011 - 2019

# Change column name from `Entity` to `country name`
suicide_df <- rename(suicide_df, `Country name` = Entity)

# Define the list of 19 countries
countries_of_interest <- c("Australia", "Belgium", "Brazil", "Canada", "Denmark",
                           "Finland", "France", "Germany", "Iceland", "Italy",
                           "Japan", "Netherlands", "New Zealand", "Norway", 
                           "South Africa", "Spain", "Sweden", "United Kingdom", 
                           "United States")

# Filter the data for the 19 countries
new_suicide<- suicide_df %>%
  filter(`Country name` %in% countries_of_interest)

# Define the date range of focus
start_year <- 2011
end_year <- 2020

# Filter the data for the date range
suicide_data <- new_suicide %>%
  filter(as.numeric(Year) >= start_year & as.numeric(Year) <= end_year)

# Show the filtered data
suicide_data %>% 
  sample_n(10)

Label headers to align all the data set & view sample data

gdp
bankruptcy_data
# Change column name from `Entity` to `country name`
gdp_data <- rename(gdp, `Country name` = `Country Name`)
bankruptcy_data<- rename(bankruptcy_data, `Country name` = `Country`)
happiness_data = rename(happiness_data, `Year` = `year`)
suicide_data %>% 
  sample_n(10)

happiness_data %>% 
  sample_n(10)

gdp_data %>% 
  sample_n(10)

bankruptcy_data %>% 
  sample_n(10)

Merging datasets

gdp_data
happiness_data
bankruptcy_data
suicide_data
# Convert "Year" column to character type in all datasets
suicide_data <- mutate(suicide_data, Year = as.character(Year))
happiness_data <- mutate(happiness_data, Year = as.character(Year))
gdp_data <- mutate(gdp_data, Year = as.character(Year))
bankruptcy_data <- mutate(bankruptcy_data, Year = as.character(Year))

# Merge the datasets
suicide_analysis <- suicide_data %>%
  left_join(happiness_data, by = c("Year", "Country name")) %>%
  left_join(gdp_data, by = c("Year", "Country name")) %>%
  left_join(bankruptcy_data, by = c("Year", "Country name"))
# View sample data from the merged dataset
suicide_analysis 

Save the dataset in excel csv format to run analysis for the final project


# # Drop specified columns
# suicide_analysis <- suicide_analysis %>%
#   select(-c("Code", "COU", "PowerCode", "PowerCode Code"))
# 
# # Save the merged dataset as a CSV file
# # Define the path to the folder on your desktop
# desktop_path <- "/home/alex/Uni/Master_US/2_Semester/Class_Data_Wrangeling_EDA/Data_Wrangling_EDA/data/"
# 
# # Create the folder if it doesn't exist
# dir.create(desktop_path, showWarnings = FALSE)
# 
# # Save the merged dataset as a CSV file in the specified folder
# write.csv(suicide_analysis, file.path(desktop_path, "suicide_analysis_2.csv"), row.names = FALSE)
library(dplyr)
library(readr)
library(tidyverse)
library(ggplot2)
library(highcharter)
library(magrittr)

EDA

Data loading

data <- read_csv("https://raw.githubusercontent.com/Alexburk93/Data_Wrangling_EDA/main/data/suicide_analysis_2.csv")
New names:Rows: 894 Columns: 19── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (10): Country name, VAR, Variable, MEA, Measure, ISIC4...14, ISIC4...15, Unit Code, Unit, Quarter
dbl  (9): Year, Age-standardized suicide rate - Sex: both sexes, Life Ladder, Social support, Healthy life expecta...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
                data %>% sample_n(19)

Renaming variables and drop unwanted columns

# renaming the columns 
data <- data %>%
  rename(`Country_name` = `Country name`,
         `Suicide_Rate` = `Age-standardized suicide rate - Sex: both sexes`,
         `Life_ladder` = `Life Ladder`,
         `Social_support` = `Social support`,
         `Life_expectancy` = `Healthy life expectancy at birth`,
         `Freedom_choices` = `Freedom to make life choices`,
         `Corruption` = `Perceptions of corruption`)
data
data
# drop columns 
# remove the original 'Time' column
data <- select(data, -Variable, -VAR, -MEA, -`Unit Code`)  
data

Data exploration

head(data)
# change names
names(data) <- make.names(names(data))
# dimensions of the dataframe
nrow(data)
[1] 894
ncol(data)
[1] 15
dim(data)
[1] 894  15
# check the structure of the object
str(data)
tibble [894 × 15] (S3: tbl_df/tbl/data.frame)
 $ Country_name   : chr [1:894] "Australia" "Australia" "Australia" "Australia" ...
 $ Year           : num [1:894] 2011 2011 2011 2011 2011 ...
 $ Suicide_Rate   : num [1:894] 10.1 10.1 10.1 10.1 11 ...
 $ Life_ladder    : num [1:894] 7.41 7.41 7.41 7.41 7.19 ...
 $ Social_support : num [1:894] 0.967 0.967 0.967 0.967 0.954 ...
 $ Life_expectancy: num [1:894] 72.3 72.3 72.3 72.3 72.1 ...
 $ Freedom_choices: num [1:894] 0.945 0.945 0.945 0.945 0.935 ...
 $ Corruption     : num [1:894] 0.382 0.382 0.382 0.382 0.269 ...
 $ GDP            : num [1:894] 62610 62610 62610 62610 38388 ...
 $ Measure        : chr [1:894] "Index 2007=100" "Index 2007=100" "Index 2007=100" "Index 2007=100" ...
 $ ISIC4...14     : chr [1:894] "01_99C" "01_99C" "01_99C" "01_99C" ...
 $ ISIC4...15     : chr [1:894] "Grand total (corporations only)" "Grand total (corporations only)" "Grand total (corporations only)" "Grand total (corporations only)" ...
 $ Unit           : chr [1:894] "Index" "Index" "Index" "Index" ...
 $ Value          : num [1:894] 132 138 143 145 122 ...
 $ Quarter        : chr [1:894] "Q1" "Q2" "Q3" "Q4" ...
# look at columns 6, 7 and 10
head(data[ , c(2, 4:6, 12, 15)])
# look at columns 6, 7 and 10
tail(data[ , c(1, 3, 9)])
table(data$Year)

2011 2012 2013 2014 2015 2016 2017 2018 2019 
 100  100  100  100  100  100  100   97   97 
data %>% 
  select(Country_name) %>% 
  unique() %>% 
  nrow()
[1] 19
unique(data$Country_name)
 [1] "Australia"      "New Zealand"    "United States"  "Spain"          "Netherlands"    "France"        
 [7] "Finland"        "Belgium"        "Japan"          "South Africa"   "Iceland"        "Norway"        
[13] "Sweden"         "Italy"          "Brazil"         "United Kingdom" "Germany"        "Canada"        
[19] "Denmark"       
unique(data$Year)
[1] 2011 2012 2013 2014 2015 2016 2017 2018 2019

Interactive maps

# Set highcharter options for tooltip decimals
options(highcharter.tooltip.valueDecimals = 2)

# Create highcharter map visualization
hc <- highchart() %>%
  hc_add_series_map(
    worldgeojson, data, value = "GDP", 
    joinBy = c('name', 'Country_name'),
    name = "GDP (current US$)"
  )  %>% 
  hc_colorAxis(stops = color_stops()) %>% 
  hc_title(text = "World Map") %>% 
  hc_subtitle(text = "GDP in current US$")

hc
# Set highcharter options for tooltip decimals
options(highcharter.tooltip.valueDecimals = 2)

# Create map visualizations for each variable
hc_life_expectancy <- highchart() %>%
  hc_add_series_map(
    worldgeojson, data, 
    value = "Life_expectancy", 
    joinBy = c('name', 'Country_name'),
    name = "Life Expectancy"
  ) %>%
  hc_colorAxis(stops = color_stops()) %>%
  hc_title(text = "World Map") %>%
  hc_subtitle(text = "Life Expectancy")

hc_suicide_rates <- highchart() %>%
  hc_add_series_map(
    worldgeojson, data, 
    value = "Suicide_Rate", 
    joinBy = c('name', 'Country_name'),
    name = "Suicide Rates"
  ) %>%
  hc_colorAxis(stops = color_stops()) %>%
  hc_title(text = "World Map") %>%
  hc_subtitle(text = "Suicide Rate")

hc_corruption <- highchart() %>%
  hc_add_series_map(
    worldgeojson, data, 
    value = "Corruption", 
    joinBy = c('name', 'Country_name'),
    name = "Corruption"
  ) %>%
  hc_colorAxis(stops = color_stops()) %>%
  hc_title(text = "World Map") %>%
  hc_subtitle(text = "Corruption")

# Display the map visualizations
list(hc_life_expectancy, hc_suicide_rates, hc_corruption)
[[1]]

[[2]]

[[3]]
NA

Analysis

AVG GDP over years

Calculation

avg_gdp_per_year <- data %>% 
  group_by (`Year`) %>% 
  summarise(avg_gpd = mean(`GDP`))

avg_gdp_per_year

Plot

ggplot(avg_gdp_per_year, aes(x = Year, y = avg_gpd)) +
  geom_line(color = "blue") +  
  labs(title = "Average GDP Over Time worldwide",
       x = "Year",
       y = "GDP") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_gdp_per_year$Year), max(avg_gdp_per_year$Year), by = 1))

AVG Happiness over years

Calculation

avg_happiness_per_year <- data %>% 
  group_by (`Year`) %>% 
  summarise(avg_happinnes = mean(`Life_ladder`, na.rm = T))

avg_happiness_per_year

Plot

ggplot(avg_happiness_per_year, aes(x = Year, y = avg_happinnes)) +
  geom_line(color = "blue") +  
  labs(title = "Average Happiness Over Time worldwide",
       x = "Year",
       y = "Happiness") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_happiness_per_year$Year), max(avg_happiness_per_year$Year), by = 1))

AVG Suicide Rates over years

Calculation

avg_Suicide_Rate_per_year <- data %>% 
  group_by (`Year`) %>% 
  summarise(avg_Suicide_Rate = mean(`Suicide_Rate`, na.rm = T))

avg_Suicide_Rate_per_year

Plot

ggplot(avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate)) +
  geom_line(color = "blue") +  
  labs(title = "Average Suicide Rate Over Time worldwide",
       x = "Year",
       y = "Suicide Rate") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_Suicide_Rate_per_year$Year), max(avg_Suicide_Rate_per_year$Year), by = 1))

AVG Bankruptcies over years

Calculation

avg_Bankruptcies_per_year <- data %>% 
  group_by (`Year`) %>% 
  summarise(avg_Bankruptcies = mean(`Value`, na.rm = T))

avg_Bankruptcies_per_year

Plot

ggplot(avg_Bankruptcies_per_year, aes(x = Year, y = avg_Bankruptcies)) +
  geom_line(color = "blue") +  
  labs(title = "Average Bankruptcies Over Time worldwide",
       x = "Year",
       y = "Bankruptcies") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_Bankruptcies_per_year$Year), max(avg_Bankruptcies_per_year$Year), by = 1))

Plot Average GDP and Average Suicide Rate over years

# Finding the ratio for scaling the second axis
ratio <- max(avg_gdp_per_year$avg_gpd) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)

# Creating the base plot
ggplot() +
  # Adding the bar plot for GDP
  geom_line(data = avg_gdp_per_year, aes(x = Year, y = avg_gpd), size = 0.5) +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 0.5) +
  # Enhancing the plot
  labs(title = "Average GDP and Suicide Rate Over Time",
       x = "Year",
       y = "Average GDP") +
  scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(c(avg_gdp_per_year$Year, avg_Suicide_Rate_per_year$Year)), 
                                  max(c(avg_gdp_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))

Plot Average Happinness and Average Suicide Rate over years

# Finding the ratio for scaling the second axis
ratio <- max(avg_happiness_per_year$avg_happinnes) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)

# Creating the base plot
ggplot() +
  # Adding the bar plot for GDP
  geom_line(data = avg_happiness_per_year, aes(x = Year, y = avg_happinnes), size = 0.5) +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 0.5) +
  # Enhancing the plot
  labs(title = "Average Happinness and Suicide Rate Over Time",
       x = "Year",
       y = "Average Happinness") +
  scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(c(avg_happiness_per_year$Year, avg_Suicide_Rate_per_year$Year)), 
                                  max(c(avg_happiness_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))

# Finding the ratio for scaling the second axis
ratio <- max(avg_happiness_per_year$avg_happinnes) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)

# Creating the base plot
ggplot() +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_happiness_per_year, aes(x = Year, y = avg_happinnes), size = 0.5) +
  # Adding the line plot for Suicide Rate adjusted by the ratio
  geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 0.5) +
  # Setting up the titles and labels
  labs(title = "Average Happiness and Suicide Rate Over Time",
       x = "Year",
       y = "Average Happiness",
       subtitle = "Suicide rates are scaled to compare against happiness") +
  # Primary axis for Happiness, secondary axis for Suicide Rate (inversed scaling)
  scale_y_continuous(name = "Average Happiness",
                     sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  # Minimalist theme with angled x-axis texts
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  # Set x-axis breaks
  scale_x_continuous(breaks = seq(min(c(avg_happiness_per_year$Year, avg_Suicide_Rate_per_year$Year)), 
                                  max(c(avg_happiness_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))

Plot Average Bankruptcies and Average Suicide Rate over years

# Finding the ratio for scaling the second axis
ratio <- max(avg_Bankruptcies_per_year$avg_Bankruptcies) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)

# Creating the base plot
ggplot() +
  # Adding the bar plot for GDP
  geom_line(data = avg_Bankruptcies_per_year, aes(x = Year, y = avg_Bankruptcies), size = 0.5) +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 0.5) +
  # Enhancing the plot
  labs(title = "Average Bankruptcies and Suicide Rate Over Time",
       x = "Year",
       y = "Average Bankruptcies") +
  scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(c(avg_Bankruptcies_per_year$Year, avg_Suicide_Rate_per_year$Year)), 
                                  max(c(avg_Bankruptcies_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))

Comparisions

Two Happiest and Two unhappiest countries vs average suicide rate

avg_Suicide_Rate_per_country = data %>%
  group_by(Country_name) %>%
  summarise(avg_suicide_rate = mean(Suicide_Rate, na.rm = TRUE)) %>%
  arrange(avg_suicide_rate) %>% 
  mutate(Row_Number = row_number())

avg_Suicide_Rate_per_country

avg_happiness_per_country <- data %>%
  group_by(Country_name) %>%
  summarise(avg_happiness = mean(Life_ladder, na.rm = TRUE)) %>%
  arrange(desc(avg_happiness))

least_happy =  tail(avg_happiness_per_country, 2)
most_happy = head(avg_happiness_per_country, 2)


avg_Suicide_Rate_per_country %>% 
  filter(Country_name %in% least_happy$Country_name)

# Interpretation: Japan and South Africa are two very unhappy countries. And they also have a high suicide rate

avg_Suicide_Rate_per_country %>% 
  filter(Country_name %in% most_happy$Country_name)

# Interpretation: Finland is a the second most happy country. But is still on place 16/19 when it comes to suicides

Two most wealthy countries and two most poor countries vs average suicide rate

avg_gdp_per_country <- data %>% 
  group_by (`Country_name`) %>% 
  summarise(avg_gpd = mean(`GDP`)) %>% 
  arrange(desc(avg_gpd))

least_gdp =  tail(avg_gdp_per_country, 2)
most_gdp = head(avg_gdp_per_country, 2)

avg_Suicide_Rate_per_country %>% 
  filter(Country_name %in% least_gdp$Country_name)

# Interpretation: Brazil with a low GPD per Capita is still low in the suicide ranking. SA has a bad GPA per Capita and is also bad in the suicide ranking  

avg_Suicide_Rate_per_country %>% 
  filter(Country_name %in% most_gdp$Country_name)

# Interpretation: The two biggest economies are based in the middle of the suicide rating

Two most bankcuptcies and two least bankcuptcies countries vs average suicide rate

avg_Bankruptcies_per_year <- data %>% 
  group_by (`Country_name`) %>% 
  summarise(avg_bankruptcies = mean(`Value`, na.rm = T)) %>% 
  arrange(desc(avg_bankruptcies))

least_bank =  tail(avg_Bankruptcies_per_year, 2)
most_bank = head(avg_Bankruptcies_per_year, 2)

avg_Suicide_Rate_per_country %>% 
  filter(Country_name %in% least_bank$Country_name)

# Interpretation: Bankruptcies don't have an influence on suicide rates

avg_Suicide_Rate_per_country %>% 
  filter(Country_name %in% most_bank$Country_name)

# Interpretation: Bankruptcies don't have an influence on suicide rates

In depth analysis Germany

Data preperation for Germany

# Prepare data for only Germany
germany_data = data %>% 
  filter(Country_name == "Germany")

Plot GDP Germany

# Plot Germany GDP over Years
avg_gdp_year_germany = germany_data %>% 
  group_by(Year) %>% 
  summarise(avg_gdp = mean(GDP)) 


ggplot(avg_gdp_year_germany, aes(x = Year, y = avg_gdp)) +
  geom_line(color = "blue") +  
  labs(title = "Average GPD Over Time - Germany",
       x = "Year",
       y = "GDP") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_gdp_year_germany$Year), max(avg_gdp_year_germany$Year), by = 1))

Plot Suicide Rate Germany

avg_suicide_year_germany = germany_data %>% 
  group_by(Year) %>% 
  summarise(avg_suicide = mean(Suicide_Rate)) 


ggplot(avg_suicide_year_germany, aes(x = Year, y = avg_suicide)) +
  geom_line(color = "blue") +  
  labs(title = "Average Suicide Rate Over Time - Germany",
       x = "Year",
       y = "Suicide Rate") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_suicide_year_germany$Year), max(avg_suicide_year_germany$Year), by = 1))

Plot Bankruptcies Rate Germany

avg_bank_year_germany = germany_data %>% 
  group_by(Year) %>% 
  summarise(avg_bank = mean(Value)) 


ggplot(avg_bank_year_germany, aes(x = Year, y = avg_bank)) +
  geom_line(color = "blue") +  
  labs(title = "Average bankruptcies Over Time - Germany",
       x = "Year",
       y = "Bankruptcies") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_bank_year_germany$Year), max(avg_bank_year_germany$Year), by = 1))

Plot Happiness Rate Germany

avg_happiness_year_germany = germany_data %>% 
  group_by(Year) %>% 
  summarise(avg_happy = mean(Life_ladder)) 


ggplot(avg_happiness_year_germany, aes(x = Year, y = avg_happy)) +
  geom_line(color = "blue") +  
  labs(title = "Average Happiness Over Time - Germany",
       x = "Year",
       y = "Happiness") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_happiness_year_germany$Year), max(avg_happiness_year_germany$Year), by = 1))

Plot Average GDP and Average Suicide Rate over years - Germany

avg_suicide_year_germany$avg_suicide
[1] 9.25 8.98 9.22 9.19 9.00 8.82 8.34 8.46 8.27
# Finding the ratio for scaling the second axis
ratio <- max(avg_gdp_year_germany$avg_gdp) / max(avg_suicide_year_germany$avg_suicide)

# Creating the base plot
ggplot() +
  # Adding the bar plot for GDP
  geom_line(data = avg_gdp_year_germany, aes(x = Year, y = avg_gdp), size = 0.5) +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_suicide_year_germany, aes(x = Year, y = avg_suicide * ratio), color = "red", size = 0.5) +
  # Enhancing the plot
  labs(title = "Average GDP and Suicide Rate Over Time",
       x = "Year",
       y = "Average GDP") +
  scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(c(avg_gdp_year_germany$Year, avg_suicide_year_germany$Year)), 
                                  max(c(avg_gdp_year_germany$Year, avg_suicide_year_germany$Year)), by = 1))

Plot Average Happinness and Average Suicide Rate over years - Germany

# Finding the ratio for scaling the second axis
ratio <- max(avg_happiness_year_germany$avg_happy) / max(avg_suicide_year_germany$avg_suicide)

# Creating the base plot
ggplot() +
  # Adding the bar plot for GDP
  geom_line(data = avg_happiness_year_germany, aes(x = Year, y = avg_happy), size = 0.5) +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_suicide_year_germany, aes(x = Year, y = avg_suicide * ratio), color = "red", size = 0.5) +
  # Enhancing the plot
  labs(title = "Average Happinness and Suicide Rate Over Time",
       x = "Year",
       y = "Average Happinness") +
  scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(c(avg_happiness_year_germany$Year, avg_suicide_year_germany$Year)), 
                                  max(c(avg_happiness_year_germany$Year, avg_suicide_year_germany$Year)), by = 1))

Plot Average Bankruptcies and Average Suicide Rate over years

# Finding the ratio for scaling the second axis
ratio <- max(avg_bank_year_germany$avg_bank) / max(avg_suicide_year_germany$avg_suicide)

# Creating the base plot
ggplot() +
  # Adding the bar plot for GDP
  geom_line(data = avg_bank_year_germany, aes(x = Year, y = avg_bank), size = 0.5) +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_suicide_year_germany, aes(x = Year, y = avg_suicide * ratio), color = "red", size = 0.5) +
  # Enhancing the plot
  labs(title = "Average Bankruptcies and Suicide Rate Over Time",
       x = "Year",
       y = "Average Bankruptcies") +
  scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(c(avg_bank_year_germany$Year, avg_suicide_year_germany$Year)), 
                                  max(c(avg_bank_year_germany$Year, avg_suicide_year_germany$Year)), by = 1))

In depth analysis South Africa

Data preperation for South Africa

# Prepare data for only Germany
SA_data = data %>% 
  filter(Country_name == "South Africa")

Plot GDP SA

# Plot SA GDP over Years
avg_gdp_year_SA = SA_data %>% 
  group_by(Year) %>% 
  summarise(avg_gdp = mean(GDP)) 



ggplot(avg_gdp_year_SA, aes(x = Year, y = avg_gdp)) +
  geom_line(color = "blue") +  
  labs(title = "Average GPD Over Time - SA",
       x = "Year",
       y = "GDP") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_gdp_year_SA$Year), max(avg_gdp_year_SA$Year), by = 1))

Plot Suicide Rate SA

avg_suicide_year_SA = SA_data %>% 
  group_by(Year) %>% 
  summarise(avg_suicide = mean(Suicide_Rate)) 


ggplot(avg_suicide_year_SA, aes(x = Year, y = avg_suicide)) +
  geom_line(color = "blue") +  
  labs(title = "Average Suicide Rate Over Time - SA",
       x = "Year",
       y = "Suicide Rate") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_suicide_year_SA$Year), max(avg_suicide_year_SA$Year), by = 1))

Plot Happiness Rate SA

avg_happiness_year_SA = SA_data %>% 
  group_by(Year) %>% 
  summarise(avg_happy = mean(Life_ladder)) 


ggplot(avg_happiness_year_SA, aes(x = Year, y = avg_happy)) +
  geom_line(color = "blue") +  
  labs(title = "Average Happiness Over Time - SA",
       x = "Year",
       y = "Happiness") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_happiness_year_SA$Year), max(avg_happiness_year_SA$Year), by = 1))

Plot Bankruptcies Rate SA

avg_bank_year_sa = SA_data %>% 
  group_by(Year) %>% 
  summarise(avg_bank = mean(Value)) 


ggplot(avg_bank_year_sa, aes(x = Year, y = avg_bank)) +
  geom_line(color = "blue") +  
  labs(title = "Average bankruptcies Over Time - SA",
       x = "Year",
       y = "Bankruptcies") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(avg_bank_year_sa$Year), max(avg_bank_year_sa$Year), by = 1))

Plot Average GDP and Average Suicide Rate over years - SA

# Finding the ratio for scaling the second axis
ratio <- max(avg_gdp_year_SA$avg_gdp) / max(avg_suicide_year_SA$avg_suicide)

# Creating the base plot
ggplot() +
  # Adding the bar plot for GDP
  geom_line(data = avg_gdp_year_SA, aes(x = Year, y = avg_gdp), size = 0.5) +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_suicide_year_SA, aes(x = Year, y = avg_suicide * ratio), color = "red", size = 0.5) +
  # Enhancing the plot
  labs(title = "Average GDP and Suicide Rate Over Time - SA",
       x = "Year",
       y = "Average GDP") +
  scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(c(avg_gdp_year_SA$Year, avg_suicide_year_SA$Year)), 
                                  max(c(avg_gdp_year_SA$Year, avg_suicide_year_SA$Year)), by = 1))

Plot Average Bankruptcies and Average Suicide Rate over years

# Finding the ratio for scaling the second axis
ratio <- max(avg_bank_year_sa$avg_bank) / max(avg_suicide_year_SA$avg_suicide)

# Creating the base plot
ggplot() +
  # Adding the bar plot for GDP
  geom_line(data = avg_bank_year_sa, aes(x = Year, y = avg_bank), size = 0.5) +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_suicide_year_SA, aes(x = Year, y = avg_suicide * ratio), color = "red", size = 0.5) +
  # Enhancing the plot
  labs(title = "Average Bankruptcies and Suicide Rate Over Time - SA",
       x = "Year",
       y = "Average Bankruptcies") +
  scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(c(avg_bank_year_sa$Year, avg_suicide_year_SA$Year)), 
                                  max(c(avg_bank_year_sa$Year, avg_suicide_year_SA$Year)), by = 1))

Plot Average Happinness and Average Suicide Rate over years - SA

# Finding the ratio for scaling the second axis
ratio <- max(avg_happiness_year_SA$avg_happy) / max(avg_suicide_year_SA$avg_suicide)

# Creating the base plot
ggplot() +
  # Adding the bar plot for GDP
  geom_line(data = avg_happiness_year_SA, aes(x = Year, y = avg_happy), size = 0.5) +
  # Adding the line plot for Average Happiness
  geom_line(data = avg_suicide_year_SA, aes(x = Year, y = avg_suicide * ratio), color = "red", size = 0.5) +
  # Enhancing the plot
  labs(title = "Average Happinness and Suicide Rate Over Time - SA",
       x = "Year",
       y = "Average Happinness") +
  scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_continuous(breaks = seq(min(c(avg_happiness_year_SA$Year, avg_suicide_year_SA$Year)), 
                                  max(c(avg_happiness_year_SA$Year, avg_suicide_year_SA$Year)), by = 1))

Conclusion and Summary

This project provided a fascinating opportunity to delve into an unfamiliar topic, applying theoretical methods learned in class to a practical, real-world project. We performed an in-depth exploration using four distinct datasets: Suicide Rate, GDP per Capita, Bankruptcies, and Happiness Index. The years were spanning from 2011 to 2019. Our initial approach involved analyzing each dataset independently to understand its composition and conducting preliminary exploratory data analysis. This included tasks such as calculating and plotting the average annual values for each dataset across the globe.

Following this foundational analysis, we progressed to the data wrangling phase. We successfully merged the four datasets. The resultant combined dataset included data from 19 countries, providing a basis for further analysis. In the analytical phase, we wanted to uncover any potential correlations within the data set of these 19 countries. Our efforts to identify significant correlations among the datasets were unsuccessful.

To gain deeper insights, we narrowed our focus to two specific countries: Germany and South Africa. For each country, we conducted a detailed exploration of their data, plotting trends over the years and searching for any correlations between the variables within each national context. Our analysis did not reveal any significant correlations.

Possible Improvments

Given the absence of correlations in our initial analyses, we recognized the necessity to widen the dataset to enhance our study. Potential for expanding our dataset include incorporating additional variables such as alcohol and drug usage, unemployment rates, and sunshine hours in the countries studied. Additionally, transitioning from an annual to a monthly data overview might bring some benefit in exploring trends and correlations that were not visible in the yearly data.

Furthermore, to enhance the quality and depth of our analysis, focusing on more granular details could provide significant insights, particularly by examining various socio-economic and political factors that influence country-specific behaviors. Incorporating additional variables such as political stability, social conflicts, and specific cultural constructs could enrich our understanding of the correlations or lack thereof in the data. These factors often have profound impacts on economic conditions, happiness indices, and social issues like suicide rates and bankruptcy, providing a more nuanced and comprehensive framework for analysis.

If given the opportunity to revisit this project from the beginning, we would integrate these broader socio-political variables from the start, allowing for a more thorough initial data collection phase. This approach would enable us to capture a wider spectrum of influences, potentially revealing hidden patterns and correlations that were not evident in our previous analysis. Moreover, employing advanced statistical methods or machine learning techniques could further aid in identifying complex interactions between variables.

Continuing this project, our next steps would involve expanding our dataset to include these additional socio-political factors and applying more sophisticated analytical techniques. This could involve time-series analysis for trend detection or cluster analysis to identify similar behavioral patterns across different countries. By doing so, we aim to build a richer analytical model that can more accurately reflect the intricate realities influencing these critical societal indicators.

LS0tCnRpdGxlOiAiUHJlc2VudGF0aW9uIC0gRG9uJ3QgY29tbWl0IFN1aWNpZGUiCmF1dGhvcjogIk1hcmNrZW5yb2xkIENhZGV0ICYgQWxleGFuZGVyIEJ1cmtoYXJ0IgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgIGh0bWxfbm90ZWJvb2s6CiAgICAgICB0b2M6IHRydWUgCiAgICAgICB0b2NfZmxvYXQ6IHRydWUKICAgICAgIHRvY19kZXB0aDogMgogICAgICAgdGhlbWU6IHVuaXRlZAogICAgICAgaGlnaGxpZ2h0OiB0YW5nbwotLS0KIyBJbnRyb2R1Y3Rpb24KClN1aWNpZGUgaXMgdGhlIGRlbGliZXJhdGUgYWN0IG9mIGVuZGluZyBvbmXigJlzIG93biBsaWZlLCBvZnRlbiBzdGVtbWluZyBmcm9tIHZhcmlvdXMgbWVudGFsIGRpc29yZGVycyBzdWNoIGFzIGRlcHJlc3Npb24sIGJpcG9sYXIgZGlzb3JkZXIsIGF1dGlzbSwgc2NoaXpvcGhyZW5pYSwgYW5kIHBlcnNvbmFsaXR5IGRpc29yZGVycywgYXMgd2VsbCBhcyBleHRlcm5hbCBzdHJlc3NvcnMgbGlrZSBmaW5hbmNpYWwgc3RydWdnbGVzLCBhY2FkZW1pYyBwcmVzc3VyZXMsIHJlbGF0aW9uc2hpcCBpc3N1ZXMsIG9yIGV4cGVyaWVuY2VzIG9mIGhhcmFzc21lbnQgYW5kIGJ1bGx5aW5nLiBGYWN0b3JzIGxpa2Ugc3Vic3RhbmNlIGFidXNlLCBpbmNsdWRpbmcgYWxjb2hvbGlzbSBhbmQgYmVuem9kaWF6ZXBpbmUgdXNlLCBhbHNvIGNvbnRyaWJ1dGUgdG8gdGhpcyB0cmFnaWMgb3V0Y29tZS4gUHJldmlvdXMgc3VpY2lkZSBhdHRlbXB0cyBzaWduaWZpY2FudGx5IGVsZXZhdGUgdGhlIHJpc2sgb2YgZnV0dXJlIGF0dGVtcHRzLgpFZmZvcnRzIHRvIHByZXZlbnQgc3VpY2lkZSBpbnZvbHZlIGEgbXVsdGlmYWNldGVkIGFwcHJvYWNoLCBpbmNsdWRpbmcgcmVzdHJpY3RpbmcgYWNjZXNzIHRvIGNvbW1vbiBtZXRob2RzIGxpa2UgZmlyZWFybXMsIGRydWdzLCBhbmQgcG9pc29ucywgYWRkcmVzc2luZyBtZW50YWwgaGVhbHRoIGlzc3VlcyBhbmQgc3Vic3RhbmNlIGFidXNlLCByZXNwb25zaWJsZSBtZWRpYSByZXBvcnRpbmcgb24gc3VpY2lkZXMsIGFuZCBmb3N0ZXJpbmcgYmV0dGVyIGVjb25vbWljIGNvbmRpdGlvbnMuIERlc3BpdGUgdGhlIHdpZGVzcHJlYWQgYXZhaWxhYmlsaXR5IG9mIGNyaXNpcyBob3RsaW5lcywgdGhlaXIgZWZmZWN0aXZlbmVzcyByZW1haW5zIGluYWRlcXVhdGVseSByZXNlYXJjaGVkLgpUaGUgcHJldmFsZW5jZSBhbmQgbWV0aG9kcyBvZiBzdWljaWRlIHZhcnkgYWNyb3NzIGNvdW50cmllcywgb2Z0ZW4gaW5mbHVlbmNlZCBieSB0aGUgYWNjZXNzaWJpbGl0eSBvZiBsZXRoYWwgbWVhbnMuIEhhbmdpbmcsIHBlc3RpY2lkZSBpbmdlc3Rpb24sIHBvaXNvbmluZywgYW5kIGZpcmVhcm1zIGFyZSBhbW9uZyB0aGUgbW9zdCBjb21tb25seSB1c2VkIG1ldGhvZHMuIEdsb2JhbGx5LCBzdWljaWRlcyBjbGFpbSBvdmVyIDcwMCwwMDAgbGl2ZXMgYW5udWFsbHksIHJhbmtpbmcgc3VpY2lkZSBhcyB0aGUgMTB0aCBsZWFkaW5nIGNhdXNlIG9mIGRlYXRoIHdvcmxkd2lkZS4KQXBwcm94aW1hdGVseSAxLjUlIG9mIHBlb3BsZSBkaWUgYnkgc3VpY2lkZSwgdHJhbnNsYXRpbmcgdG8gcm91Z2hseSAxMiBwZXIgMTAwLDAwMCBpbmRpdmlkdWFscyBlYWNoIHllYXIuIE1lbiBhcmUgbW9yZSBsaWtlbHkgdG8gZGllIGJ5IHN1aWNpZGUgdGhhbiB3b21lbiwgd2l0aCByYXRlcyByYW5naW5nIGZyb20gMS41IHRpbWVzIGhpZ2hlciBpbiBkZXZlbG9waW5nIGNvdW50cmllcyB0byAzLjUgdGltZXMgaGlnaGVyIGluIGRldmVsb3BlZCBvbmVzLiBGaW5hbmNpYWwgc3RyYWluIG9mdGVuIGV4YWNlcmJhdGVzIHRoZSByaXNrIG9mIHN1aWNpZGUuIFsxXQoKIyBSZWxhdGVkIFdvcmsKCiMjIFRpdGxlOiBBIFN0dWR5IGZvciBFZmZlY3RzIG9mIEVjb25vbWljIEdyb3d0aCBSYXRlIGFuZCBVbmVtcGxveW1lbnQgUmF0ZSB0byBTdWljaWRlIFJhdGUgaW4gS29yZWEKCkF1dGhvcjogSm9uZyBTb29uIFBhcmssIEp1bmUgWW91bmcgTGVlLCBTb29uIER1Y2sgS2ltCk9iamVjdGl2ZXM6IFdlIGludmVzdGlnYXRlZCB0aGUgZWZmZWN0cyBvZiB0aGUgZWNvbm9taWMgZ3Jvd3RoIGFuZCB1bmVtcGxveW1lbnQgcmF0ZXMgb24gdGhlIHN1aWNpZGUgcmF0ZSBpbiBLb3JlYSwgYmV0d2VlbiAxOTgzIGFuZCAyMDAwLCB1c2luZyBhIHRpbWUtc2VyaWVzIHJlZ3Jlc3Npb24gbW9kZWwuIFRoZSBwdXJwb3NlIG9mIHRoaXMgc3R1ZHkgd2FzIHRvIG1vZGVsIGFuZCB0ZXN0IHRoZSBtYWduaXR1ZGUgb2YgdGhlIHJhdGUgb2Ygc3VpY2lkZSwgd2l0aCB0aGUgS29yZWFuIHVuZW1wbG95bWVudCByYXRlIGFuZCBHRFAuIFsyXQoKQ29uY2x1c2lvbjogSXQgd2FzIGZvdW5kIHRoYXQgdGhlIHN1aWNpZGUgcmF0ZSB3YXMgY2xvc2VseSByZWxhdGVkIHRvIHRoZSBOYXRpb25hbOKAmXMgZWNvbm9taWMgc3RhdHVzIG9mIEtvcmVhLCB3aGljaCBpcyBzaW1pbGFyIHRvIHRoZSByZXN1bHRzIGZvdW5kIGluIHN0dWRpZXMgaW4gb3RoZXIgY291bnRyaWVzLiBXZSBleHBlY3RlZCwgdGhlcmVmb3JlLCB0aGF0IHRoaXMgc3R1ZHkgY291bGQgYmUgdXNlZCBhcyB0aGUgYmFzaXMgZm9yIGZ1cnRoZXIgc3VpY2lkZS1yZWxhdGVkIHN0dWRpZXMuIFsyXQoKIyMgVGl0bGU6IFRlbi15ZWFyIGV2b2x1dGlvbiBvZiBzdWljaWRlIHJhdGVzIGFuZCBlY29ub21pYyBpbmRpY2F0b3JzIGluIGxhcmdlIEJyYXppbGlhbiB1cmJhbiBjZW50ZXJzCgpBdXRob3I6IEFzZXZlZG8gRWxzb24sIFppZWJvbGQgQ2Fyb2xpbmEsIERpbml6IEVsdG9uLCBHYWRlbGhhIEFyeSwgTWFyaSBKYWlyClB1cnBvc2Ugb2YgcmV2aWV3OiBUaGlzIHdhcyBhIHJldHJvc3BlY3RpdmUgZWNvbG9naWNhbCBzdHVkeSB0byBleGFtaW5lIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzdWljaWRlIHJhdGVzIGFuZCBlY29ub21pYyBpbmRpY2F0b3JzIGluIGxhcmdlIEJyYXppbGlhbiB1cmJhbiBjZW50ZXJzLiBEYXRhIG9uIG1hY3JvZWNvbm9taWMgaW5kaWNhdG9ycyAoR0RQIGFuZCB1bmVtcGxveW1lbnQgcmF0ZXMpIGFuZCBzdWljaWRlIHJhdGVzIG9mIHRoZSBsYXJnZXN0IEJyYXppbGlhbiBjaXRpZXMgd2VyZSBjb2xsZWN0ZWQgZnJvbSBKYW51YXJ5IDIwMDYgdG8gRGVjZW1iZXIgMjAxNS4gWzNdClN1bW1hcnkgVGhlIGVmZmVjdCBvZiBlY29ub21pYyBpbmRpY2F0b3JzIHdhcyBoZXRlcm9nZW5lb3VzIGFtb25nIHRoZSBjZW50ZXJzLCBidXQsIG92ZXJhbGwsIHRoZSB2YXJpYXRpb24gaW4gc3VpY2lkZSByYXRlcyB3YXMgaW52ZXJzZWx5IHJlbGF0ZWQgdG8gdW5lbXBsb3ltZW50IGFuZCBkaWQgbm90IHNob3cgYSBzaWduaWZpY2FudCByZWxhdGlvbnNoaXAgd2l0aCBHRFAuIFRoZXNlIGZpbmRpbmdzIGluZGljYXRlIGEgbW9yZSBjb21wbGV4IGxpbmsgYmV0d2VlbiBlY29ub21pY3MgYW5kIHN1aWNpZGUgd2hlbmV2ZXIgbG9va2luZyBhdCBsb2NhbCByZWdpb25hbCBpbmRpY2F0b3JzLiBGdXJ0aGVyIHJlc2VhcmNoIHNob3VsZCBmb2N1cyBvbiBwb3NzaWJsZSBpbnRlcnZlbmluZyBmYWN0b3JzLCB3aGF0IG1heSBpbmZvcm0gYmV0dGVyIHByZXZlbnRpdmUgaW50ZXJ2ZW50aW9ucy4gWzNdCgojIyBUaXRsZTogVGhlIGFzc29jaWF0aW9uIGJldHdlZW4gbmF0aW9uLWxldmVsIHNvY2lhbCBhbmQgZWNvbm9taWMgaW5kaWNlcyBhbmQgc3VpY2lkZSByYXRlczogQSBwaWxvdCBzdHVkeQoKQXV0aG9yOiBSYXZpIFBoaWxpcCBSYWprdW1hcgpJbnRyb2R1Y3Rpb24gU3VpY2lkZSBpcyBvbmUgb2YgdGhlIGxlYWRpbmcgY2F1c2VzIG9mIHByZW1hdHVyZSBtb3J0YWxpdHkgd29ybGR3aWRlLiBBbiBhbmFseXNpcyBvZiBnbG9iYWwgc3VpY2lkZSBkYXRhIGZvciB0aGUgcGVyaW9kIDE5OTDigJMyMDE2LCBjb3ZlcmluZyAxOTUgY291bnRyaWVzLCBmb3VuZCB0aGF0IHN1aWNpZGUgd2FzIGFtb25nIHRoZSB0ZW4gbGVhZGluZyBjYXVzZXMgb2YgeWVhcnMgb2YgbGlmZSBsb3N0IGluIEV1cm9wZSwgdGhlIEFtZXJpY2FzIGFuZCB0aGUgQXNpYS1QYWNpZmljIHJlZ2lvbiAoTmFnaGF2aSwgMjAxOSkuIEJlY2F1c2Ugb2YgdGhpcywgc3VpY2lkZSBwcmV2ZW50aW9uIGhhcyBiZWVuIGFjY29yZGVkIG9uZSBvZiB0aGUgaGlnaGVzdCBwcmlvcml0aWVzIGluIG5hdGlvbmFsIGFuZCBpbnRlcm5hdGlvbmFsIHB1YmxpYyBoZWFsdGggcGxhbnMsIHN1Y2ggYXMgdGhlIFdvcmxkIEhlYWx0aCBPcmdhbml6YXRpb27igJlzIENvbXByZWhlbnNpdmUgTWVudGFsIEhlYWx0aCBBY3Rpb24gUGxhbiAoV29ybGQgSGVhbHRoIE9yZ2FuaXphdGlvbiwgMjAyMSkuIFRoZSBhY3Qgb2Ygc3VpY2lkZSBpcyBhIGNvbXBsZXggYmVoYXZpb3Igd2hpY2ggcmVzdWx0cyBmcm9tIHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIGFuIGlubmF0ZSBkaWF0aGVzaXMgYW5kIGV4dGVybmFsIHN0cmVzc29ycyAodmFuIEhlZXJpbmdlbiwgMjAxMikuIFs0XQpDb25jbHVzaW9ucyBTb2NpYWwgZmFjdG9ycyBhcmUgaW1wb3J0YW50IGRldGVybWluYW50cyBvZiBzdWljaWRlLiBEZXNwaXRlIGNlcnRhaW4gbGltaXRhdGlvbnMsIHRoZSByZXN1bHRzIG9mIHRoZSBjdXJyZW50IHN0dWR5IHN1Z2dlc3QgdGhhdCBzdXN0YWluYWJsZSBkZXZlbG9wbWVudCBtYXkgcGxheSBhIHJvbGUgaW4gdGhlIG1pdGlnYXRpb24gb2Ygc3VpY2lkZSByaXNrLCBFY29ub21pYyBpbmVxdWFsaXR5IG1heSBjb250cmlidXRlIHRvIHZhcmlhdGlvbnMgaW4gc3VpY2lkZSByaXNrLCBwYXJ0aWN1bGFybHkgaW4gbWVuLiBNb3Jlb3ZlciwgdGhlIHN0cmVuZ3RoIGFuZCBkaXJlY3Rpb24gb2YgdGhlIGFzc29jaWF0aW9ucyBiZXR3ZWVuIHNvY2lvZWNvbm9taWMgZmFjdG9ycyBhbmQgc3VpY2lkZSB2YXJpZXMgYWNyb3NzIGluY29tZSBncm91cHMsIGhpZ2hsaWdodGluZyB0aGUgbmVlZCBmb3IgYW4gaW4tZGVwdGggdW5kZXJzdGFuZGluZyBvZiBlYWNoIGNvdW50cnnigJlzIHNvY2lhbCwgY3VsdHVyYWwgYW5kIGVjb25vbWljIHByb2ZpbGUgd2hlbiBwbGFubmluZyBsYXJnZS1zY2FsZSBzb2NpYWwgaW50ZXJ2ZW50aW9ucyBhaW1lZCBhdCBzdWljaWRlIHByZXZlbnRpb24uIFs0XQoKIyMgVGl0bGU6SXMgSGFwcGluZXNzIHRoZSBtYWluIGNhdXNlIGZvciB0aGUgcmlzaW5nIHN1aWNpZGUgcmF0ZSBpbiB0aGUgd29ybGQ/CgpBdXRob3I6IEJvbmcgSmluIEhhdywgQ2hvbmcgWW9jayBMb29uLCBUYWkgSG9uZyBUaW5nLCBUZW9oIEthaCBDaHVuLCBXb25nIENoaW4gSGluZwpJbnRyb2R1Y3Rpb24gVGhpcyBzdHVkeSBpbnZlc3RpZ2F0ZXMgdGhlIGltcGFjdCBvZiBoYXBwaW5lc3Mgb24gc3VpY2lkZSByYXRlLiBCZXNpZGUgdGhlaW1wYWN0IG9mIGhhcHBpbmVzcywgZW1wbG95bWVudCwgZ3Jvc3MgZG9tZXN0aWMgcHJvZHVjdCwgZWR1Y2F0aW9uLCBoZWFsdGggZXhwZW5kaXR1cmUgYW5kIHBvcHVsYXRpb24gb24gdGhlIHN1aWNpZGUgcmF0ZSBpcyBhbHNvIHN0dWRpZWQuIFRoZSBzdHVkeSBkaXZpZGVzIHRoZSBkYXRhIGludG8gdGhyZWUgc2V0cyBpbmNsdWRpbmcgMzEgZGV2ZWxvcGVkIGFuZCBkZXZlbG9waW5nIGNvdW50cmllcywgMjYgZGV2ZWxvcGVkIGNvdW50cmllcywgYW5kIDUgZGV2ZWxvcGluZyBjb3VudHJpZXMuIEEgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIGJldHdlZW4gaGFwcGluZXNzIGFuZCB0aGUgc3VpY2lkZSByYXRlIGlzIGZvdW5kIGluIGRldmVsb3BpbmcgY291bnRyaWVzLiBbNV0KQ29uY2x1c2lvbnMgU3VycHJpc2luZ2x5LCBiYXNlZCBvbiB0aGUgcmVzdWx0IGl0IGNhbiBiZSBjb25jbHVkZWQgdGhhdCB0aGUgaGFwcGluZXNzIGluIGRldmVsb3BpbmcgY291bnRyaWVzIHdpbGwgc2lnbmlmaWNhbnRseSBpbXBhY3QgYW5kIGluZmx1ZW5jZSB0aGUgc3VpY2lkZSByYXRlIGluZGVlZC4gSXQgaXMgaW1wb3J0YW50IHRvIHJlYWxpemUgdGhhdCB0aGUgaGFwcGluZXNzIGlzIG5lZ2F0aXZlbHkgYWZmZWN0IHRoZSBzdWljaWRlIHJhdGUgaW4gZGV2ZWxvcGluZyBjb3VudHJpZXMgd2hpY2ggbWVhbnMgdGhhdCBpbmNyZWFzZSBpbiB0aGUgaGFwcGluZXNzIHdpbGwgc3Vic2VxdWVudGx5IGxvd2VyIGRvd24gdGhlIHN1aWNpZGUgcmF0ZS4gTW9yZW92ZXIsIG90aGVyIGVjb25vbWljIGZhY3RvcnMgc3VjaCBhcyBlbXBsb3ltZW50LCBncm9zcyBkb21lc3RpYyBwcm9kdWN0LCBnb3Zlcm5tZW50IGhlYWx0aCBleHBlbmRpdHVyZSwgZWR1Y2F0aW9uIGFuZCBwb3B1bGF0aW9uIGFyZSBhbHNvIGluY2x1ZGVkIGluIHRoaXMgc3R1ZHkgdG8gY2Fycnkgb3V0IHRoZWlyIGltcGFjdCB0b3dhcmRzIHRoZSBzdWljaWRlIHJhdGUuIFs1XQoKIyMgU291cmNlcwpbMV0gaHR0cHM6Ly93d3cuaWFzcC5pbmZvL3dzcGQvcmVmZXJlbmNlcy8gPGJyPgpbMl0gaHR0cHM6Ly93d3cuanBtcGgub3JnL2pvdXJuYWwvdmlldy5waHA/bnVtYmVyPTUwICh2aXNpdGVkIDAzLzI0LzIwMjQpIDxicj4KWzNdIGh0dHBzOi8vam91cm5hbHMubHd3LmNvbS9jby1wc3ljaGlhdHJ5L2Fic3RyYWN0LzIwMTgvMDUwMDAvdGVuX3llYXJfZXZvbHV0aW9uX29mX3N1aWNpZGVfcmF0ZXNfYW5kX2Vjb25vbWljLjE1LmFzcHgKKHZpc2l0ZWQgMDMvMjIvMjAyNCkgPGJyPgpbNF0gaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2FydGljbGVzLzEwLjMzODkvZnNvYy4yMDIzLjExMjMyODQvZnVsbCA8YnI+Cls1XSBodHRwOi8vZXByaW50cy51dGFyLmVkdS5teS8yODY5LzEvZnlwX0JGXzIwMThfQkpIXy1fMTQwMzMxMi5wZGYgPGJyPgoKCiMgUmVzZWFyY2ggUXVlc3Rpb24KClN1aWNpZGUgaXMgbm90IGNvbmZpbmVkIHRvIGhpZ2gtaW5jb21lIGNvdW50cmllczsgaXQgaXMgYSBnbG9iYWwgaXNzdWUgYWZmZWN0aW5nIGFsbCByZWdpb25zLiBTdXJwcmlzaW5nbHksIG92ZXIgNzclIG9mIHN1aWNpZGVzIG9jY3VyIGluIGxvdy0gYW5kIG1pZGRsZS1pbmNvbWUgY291bnRyaWVzLiBIb3dldmVyLCBoaWdoLWluY29tZSBjb3VudHJpZXMgZXhoaWJpdCB0aGUgaGlnaGVzdCBhZ2Utc3RhbmRhcmRpemVkIHN1aWNpZGUgcmF0ZXMuIEluIG9uZ29pbmcgcmVzZWFyY2ggYWNyb3NzIDE5IGNvdW50cmllcywgd2UgZXhwbG9yZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiBHRFAsIGJhbmtydXB0Y3kgcmF0ZXMsIGhhcHBpbmVzcyBsZXZlbHMsIGFuZCBzdWljaWRlIHJhdGVzLiBVbmRlcnN0YW5kaW5nIHRoZXNlIGludHJpY2F0ZSByZWxhdGlvbnNoaXBzIGlzIHBpdm90YWwgZm9yIHBvbGljeW1ha2VycywgcmVzZWFyY2hlcnMsIGFuZCBzdGFrZWhvbGRlcnMgdG8gZGV2aXNlIGVmZmVjdGl2ZSBpbnRlcnZlbnRpb25zIHByb21vdGluZyBtZW50YWwgd2VsbC1iZWluZyBhbmQgZWNvbm9taWMgcmVzaWxpZW5jZS4gTGV2ZXJhZ2luZyBtdWx0aWRpbWVuc2lvbmFsIGRhdGFzZXRzIGFuZCBhZHZhbmNlZCBhbmFseXRpY2FsIG1ldGhvZHMsIG91ciBwcm9qZWN0IGFpbXMgdG8gaWxsdW1pbmF0ZSB0aGVzZSBjb25uZWN0aW9ucyBmb3IgdGhlIGJldHRlcm1lbnQgb2Ygc29jaWV0aWVzIHdvcmxkd2lkZS4KCiMgRGF0YSBXcmFuZ2xpbmcKCmBgYHtyfQojIExvYWQgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoaHR0cikKYGBgCgojIyBFeHBsb3JhdGlvbiBvZiB0aGUgQmFua3J1cHRjaWVzIERhdGFzZXQKYGBge3J9CgojIExvYWQgZGF0YXNldApiYW5rcnVwdGNpZXMgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9BbGV4YnVyazkzL0RhdGFfV3JhbmdsaW5nX0VEQS9tYWluL2RhdGEvcmF3X2RhdGEvQmFua3J1cHRjaWVzXzIwMTEtMjAyMC5jc3YiKQoKIyBEaXNwbGF5IHN0cnVjdHVyZSBvZiBkYXRhc2V0CnN0cihiYW5rcnVwdGNpZXMpCgojIFNob3cgdGhlIGZpcnN0IGZldyByb3dzIApoZWFkKGJhbmtydXB0Y2llcykKCiMgU3VtbWFyeSBzdGF0aXN0aWNzIG9mIG51bWVyaWNhbCBhdHRyaWJ1dGVzCnN1bW1hcnkoYmFua3J1cHRjaWVzKQoKIyBTdW1tYXJ5IHN0YXRpc3RpY3Mgb2YgY2F0ZWdvcmljYWwgYXR0cmlidXRlCnRhYmxlKGJhbmtydXB0Y2llcyRDb3VudHJ5KQoKIyBDaGVjayBmb3IgbWlzc2luZyB2YWx1ZXMKc3VtKGlzLm5hKGJhbmtydXB0Y2llcykpCgojIFJlbW92aW5nIE5BJ3MgY29sdW1ucyBhbmQgVGltZSAoRHVwbGljYXRlKSAgCmRhdGEgPC0gc2VsZWN0KGJhbmtydXB0Y2llcywgLWBGbGFnIENvZGVzYCwgLUZsYWdzLCAtYFJlZmVyZW5jZSBQZXJpb2QgQ29kZWAsIC1gUmVmZXJlbmNlIFBlcmlvZGAsIC1USU1FKQpkYXRhICU+JSAKICBzYW1wbGVfbigxMCkKCiMgRGlzcGxheSB0aGUgc3RydWN0dXJlIG9mIHRoZSBtb2RpZmllZCBkYXRhc2V0CnN0cihkYXRhKQoKIyBDaGVjayB0aGUgZGltZW5zaW9uIG9mIGRhdGEKZGltKGRhdGEpCgpgYGAKCkZvciB0aGlzIHByb2plY3QsIHdlIGFyZSBvbmx5IGZvY3VzaW5nIG9uIGluZm9ybWF0aW9uIGZyb20gMjAxMSB0byAyMDIwLiBBbmQgdG8gbWluaW1pemUgdGhlIHdvcmtsb2FkLCB3ZSBhcmUgYW5hbHl6aW5nIDE5IGNvdW50cmllcy4gCmBgYHtyfQojIENyZWF0ZSBuZXcgY29sdW1ucyAnUXVhcnRlcicgYW5kICdZZWFyJyBmcm9tICdUaW1lJwpuZXdfZGF0YSA8LSBtdXRhdGUoZGF0YSwKICAgICAgICAgICAgICAgICAgIFF1YXJ0ZXIgPSBzdHJfc3ViKFRpbWUsIDEsIDIpLCAjIEV4dHJhY3QgUXVhcnRlcgogICAgICAgICAgICAgICAgICAgWWVhciA9IGFzLm51bWVyaWMoc3RyX3N1YihUaW1lLCA0KSkpICMgRXh0cmFjdCBZZWFyIGFuZCBjb252ZXJ0IHRvIG51bWVyaWMKCiMgcmVtb3ZlIHRoZSBvcmlnaW5hbCAnVGltZScgY29sdW1uCm5ld19kYXRhIDwtIHNlbGVjdChuZXdfZGF0YSwgLVRpbWUpICAKbmV3X2RhdGEKCiMgR2V0IGRhdGUgcmFuZ2UKZGF0ZV9yYW5nZSA8LSByYW5nZShuZXdfZGF0YSRZZWFyKQoKIyBDb3VudCB1bmlxdWUgY291bnRyaWVzCm5fY291bnRyaWVzIDwtIGxlbmd0aCh1bmlxdWUobmV3X2RhdGEkQ291bnRyeSkpCgojIFByaW50IHRoZSByZXN1bHRzCm5fY291bnRyaWVzCmRhdGVfcmFuZ2UKCiMgT25seSBuZWVkIGRhdGEgZnJvbSAyMDExLTIwMjAsIGV4Y2x1ZGluZyAyMDIxCmJhbmtydXB0Y3lfZGF0YSA8LSBmaWx0ZXIobmV3X2RhdGEsIFllYXIgIT0gMjAyMSkKbmV3X2RhdGEKCiMgR2V0IGRhdGUgcmFuZ2Ugb2YgbmV3IHVwZGF0ZWQgZGF0YXNldApkYXRlX3JhbmdlIDwtIHJhbmdlKGJhbmtydXB0Y3lfZGF0YSRZZWFyKQoKIyBFeHRyYWN0IHN0YXJ0IGFuZCBlbmQgeWVhcnMgZnJvbSB0aGUgcmFuZ2UKc3RhcnRfeWVhciA8LSBkYXRlX3JhbmdlWzFdCmVuZF95ZWFyIDwtIGRhdGVfcmFuZ2VbMl0KCiMgQ291bnQgdW5pcXVlIGNvdW50cmllcwpuX2NvdW50cmllcyA8LSBsZW5ndGgodW5pcXVlKGJhbmtydXB0Y3lfZGF0YSRDb3VudHJ5KSkKCiMgUHJpbnQgdGhlIHJlc3VsdHMKY2F0KCJOdW1iZXIgb2YgY291bnRyeTogIiwgbl9jb3VudHJpZXMsICJcbiIpIApjYXQoIkRhdGUgcmFuZ2UgZnJvbTogIiwgc3RhcnRfeWVhciwgIiB0byAiLCBlbmRfeWVhciwgIlxuIikKYGBgCgojIyBFeHBsb3JpbmcgR0RQIGRhdGFzZXQgJiBhbmFseXplIGZvdW5kaW5ncwpgYGB7cn0KIyBMb2FkIGRhdGFzZXQgCm15X2RhdGEgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9BbGV4YnVyazkzL0RhdGFfV3JhbmdsaW5nX0VEQS9tYWluL2RhdGEvcmF3X2RhdGEvR0RQX0RhdGEvR0RQX2NhcGl0YV8xOTYwXzIwMjIuY3N2IikKbXlfZGF0YQpgYGAKClRoZSBZZWFycyBhcmUgaW4gdGhlIGhlYWRlciwgdXNpbmcgYHBpdm90X2xvbmdlcigpYCB0byBjb252ZXJ0IGludG8gdHdvIGNvbHVtbiBZZWFyIGFuZCBHRFAKYGBge3J9CiMgUGl2b3QgdGhlIGRhdGEgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0CmpveSA8LSBwaXZvdF9sb25nZXIobXlfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xzID0gLWMoYENvdW50cnkgTmFtZWApLAogICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiWWVhciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIkdEUCIpCgojIFNob3cgdGhlIGZpcnN0IGZldyByb3dzCgpgYGAKCgpQZXJmb20gYHN1bW1hcnkgc3Rhc3RpY3NgLCBjaGVjayBmb3IgYE5BJ3NgLCBkaW1lbnNpb24gYGRpbSgpYCwgZXRjLiAKYGBge3J9CiMgRGlzcGxheSBzdHJ1Y3R1cmUgb2YgZGF0YXNldApzdHIoam95KQoKIyBTaG93IHRoZSBmaXJzdCBmZXcgcm93cyAKaGVhZChqb3kpCgojIFN1bW1hcnkgc3RhdGlzdGljcyBvZiBudW1lcmljYWwgYXR0cmlidXRlcwpzdW1tYXJ5KGpveSkKCiMgU3VtbWFyeSBzdGF0aXN0aWNzIG9mIGNhdGVnb3JpY2FsIGF0dHJpYnV0ZQp0YWJsZShqb3kkYEluZGljYXRvciBDb2RlYCkKCiMgQ2hlY2sgZm9yIG1pc3NpbmcgdmFsdWVzCnN1bShpcy5uYShqb3kpKQoKIyBDaGVjayB0aGUgZGltZW5zaW9uIG9mIGRhdGEKZGltKGpveSkKYGBgCgpGaWx0ZXIgdGhlIGRhdGEgdG8gb25seSBzaG93IHRoZSAxOSBjb3VudHJpZXMgYW5kIHRoZSBkYXRlIHJhbmdlIHRoZSBwcm9qZWN0IGlzIGZvY3VzZWQgb24uCgpgYGB7cn0KIyBEZWZpbmUgdGhlIGxpc3Qgb2YgMTkgY291bnRyaWVzCmNvdW50cmllc19vZl9pbnRlcmVzdCA8LSBjKCJBdXN0cmFsaWEiLCAiQmVsZ2l1bSIsICJCcmF6aWwiLCAiQ2FuYWRhIiwgIkRlbm1hcmsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiRmlubGFuZCIsICJGcmFuY2UiLCAiR2VybWFueSIsICJJY2VsYW5kIiwgIkl0YWx5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIkphcGFuIiwgIk5ldGhlcmxhbmRzIiwgIk5ldyBaZWFsYW5kIiwgIk5vcndheSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAiU291dGggQWZyaWNhIiwgIlNwYWluIiwgIlN3ZWRlbiIsICJVbml0ZWQgS2luZ2RvbSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAiVW5pdGVkIFN0YXRlcyIpCgojIEZpbHRlciB0aGUgZGF0YSBmb3IgdGhlIDE5IGNvdW50cmllcwpnZHAgPC0gam95ICU+JQogIGZpbHRlcihgQ291bnRyeSBOYW1lYCAlaW4lIGNvdW50cmllc19vZl9pbnRlcmVzdCkKCiMgRGVmaW5lIHRoZSBkYXRlIHJhbmdlIG9mIGZvY3VzCnN0YXJ0X3llYXIgPC0gMjAxMQplbmRfeWVhciA8LSAyMDIwCgojIEZpbHRlciB0aGUgZGF0YSBmb3IgdGhlIGRhdGUgcmFuZ2UKZ2RwIDwtIGdkcCAlPiUKICBmaWx0ZXIoYXMubnVtZXJpYyhZZWFyKSA+PSBzdGFydF95ZWFyICYgYXMubnVtZXJpYyhZZWFyKSA8PSBlbmRfeWVhcikKCiMgU2hvdyB0aGUgZmlsdGVyZWQgZGF0YQpnZHAgJT4lIAogIHNhbXBsZV9uKDEwKQpgYGAKCmBgYHtyfQojIERpc3BsYXkgc3RydWN0dXJlIG9mIGRhdGFzZXQKc3RyKGdkcCkKCiMgQ29udmVydCBZZWFyIHRvIG51bWVyaWMgCiMgZ2RwJFllYXIgPC0gYXMubnVtZXJpYyhnZHAkWWVhcikKCiMgU2hvdyB0aGUgZmlyc3QgZmV3IHJvd3MgCmhlYWQoZ2RwKQoKIyBTdW1tYXJ5IHN0YXRpc3RpY3Mgb2YgbnVtZXJpY2FsIGF0dHJpYnV0ZXMKc3VtbWFyeShnZHApCgojIFN1bW1hcnkgc3RhdGlzdGljcyBvZiBjYXRlZ29yaWNhbCBhdHRyaWJ1dGUKdGFibGUoZ2RwJGBJbmRpY2F0b3IgQ29kZWApCgojIENoZWNrIGZvciBtaXNzaW5nIHZhbHVlcwpzdW0oaXMubmEoZ2RwKSkKCiMgQ2hlY2sgdGhlIGRpbWVuc2lvbiBvZiBkYXRhCmRpbShnZHApCmBgYAoKYGBge3J9CiMgR3JvdXAgdGhlIGZpbHRlcmVkIGRhdGEgYnkgWWVhciBhbmQgY2FsY3VsYXRlIHRoZSBtZWFuIEdEUCBmb3IgZWFjaCB5ZWFyCm1lYW5fZ2RwX2J5X3llYXIgPC0gZ2RwICU+JQogIGdyb3VwX2J5KFllYXIpICU+JQogIHN1bW1hcml6ZShtZWFuX0dEUCA9IG1lYW4oR0RQLCBuYS5ybSA9IFRSVUUpKQoKIyBTaG93IHRoZSBtZWFuIEdEUCBmb3IgZWFjaCB5ZWFyCnByaW50KG1lYW5fZ2RwX2J5X3llYXIpCmBgYApWaXN1YWxpemF0aW9uIGZvciB0b3AgMTAgaGlnaGVzdCBHRFAgYnkgQ291bnJpZXMgT3ZlciBUaW1lLgoKYGBge3J9CiMgRmlsdGVyIHRvIGluY2x1ZGUgb25seSB0aGUgdG9wIDEwIGNvdW50cmllcyB3aXRoIHRoZSBoaWdoZXN0IEdEUCB2YWx1ZXMKdG9wXzEwX2dkcCA8LSBnZHAgJT4lCiAgZ3JvdXBfYnkoYENvdW50cnkgTmFtZWApICU+JQogIHN1bW1hcml6ZSh0b3RhbF9nZHAgPSBzdW0oR0RQLCBuYS5ybSA9IFRSVUUpKSAlPiUKICB0b3BfbigxMCwgdG90YWxfZ2RwKSAlPiUKICBsZWZ0X2pvaW4oZ2RwLCBieSA9ICJDb3VudHJ5IE5hbWUiKQoKIyBDb252ZXJ0IEdEUCB2YWx1ZXMgdG8gbWlsbGlvbnMgb3IgYmlsbGlvbnMKdG9wXzEwX2dkcCA8LSB0b3BfMTBfZ2RwICU+JQogIG11dGF0ZShHRFBfZm9ybWF0dGVkID0gY2FzZV93aGVuKAogICAgR0RQID49IDFlMTIgfiBwYXN0ZTAocm91bmQoR0RQIC8gMWUxMiwgMSksICJUIiksICAjIENvbnZlcnQgdG8gdHJpbGxpb25zCiAgICBHRFAgPj0gMWU5IH4gcGFzdGUwKHJvdW5kKEdEUCAvIDFlOSwgMSksICJCIiksICAjIENvbnZlcnQgdG8gYmlsbGlvbnMKICAgIEdEUCA+PSAxZTYgfiBwYXN0ZTAocm91bmQoR0RQIC8gMWU2LCAxKSwgIk0iKSwgICAjIENvbnZlcnQgdG8gbWlsbGlvbnMKICAgIFRSVUUgfiBhcy5jaGFyYWN0ZXIoR0RQKSAgICAgICAgICAgICAgICAgICAgICAgICMgS2VlcCB1bmNoYW5nZWQgaWYgbGVzcyB0aGFuIDEgbWlsbGlvbgogICkpCgojIENyZWF0ZSBhIGxpbmUgcGxvdCBvZiBHRFAgb3ZlciB0aW1lIHdpdGggZm9ybWF0dGVkIHZhbHVlcyBmb3IgdGhlIHRvcCAxMCBjb3VudHJpZXMKZ2dwbG90KHRvcF8xMF9nZHAsIGFlcyh4ID0gWWVhciwgeSA9IEdEUCwgZ3JvdXAgPSBgQ291bnRyeSBOYW1lYCkpICsKICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gYENvdW50cnkgTmFtZWApKSArCiAgbGFicyh0aXRsZSA9ICJHRFAgVHJlbmRzIE92ZXIgVGltZSAoVG9wIDEwIENvdW50cmllcykiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiR0RQIiwKICAgICAgIGNvbG9yID0gIkNvdW50cnkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4LCAiIikpICsgICMgRW5zdXJlIHktYXhpcyBsYWJlbHMgYXJlIGNoYXJhY3RlciB0eXBlCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKCk5vdGUgdGhhdCB0aGUgYGVjaG8gPSBGQUxTRWAgcGFyYW1ldGVyIHdhcyBhZGRlZCB0byB0aGUgY29kZSBjaHVuayB0byBwcmV2ZW50IHByaW50aW5nIG9mIHRoZSBSIGNvZGUgdGhhdCBnZW5lcmF0ZWQgdGhlIHBsb3QuCgoKIyMgRXhwbG9yYXRpb24gb2YgdGhlIFN1aWNpZGUgUmF0ZSBEYXRhc2V0CmBgYHtyfQojIExvYWQgZGF0YSBzZXQgZnJvbSBnaXRodWIKc3VpY2lkZV9kZiA9IHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQWxleGJ1cms5My9EYXRhX1dyYW5nbGluZ19FREEvbWFpbi9kYXRhL3Jhd19kYXRhL2RlYXRoLXJhdGUtZnJvbS1zdWljaWRlcy1naG8lMjBuZXcuY3N2IikKYGBgCmBgYHtyfQpzdWljaWRlX2RmJGBBZ2Utc3RhbmRhcmRpemVkIHN1aWNpZGUgcmF0ZSAtIFNleDogYm90aCBzZXhlc2AgPSBhcy5kb3VibGUoc3VpY2lkZV9kZiRgQWdlLXN0YW5kYXJkaXplZCBzdWljaWRlIHJhdGUgLSBTZXg6IGJvdGggc2V4ZXNgKQpzdW1tYXJ5KHN1aWNpZGVfZGYpCgojIENvbnNpZGVyIHJlbW92aW5nIExlc290aG8gZnJvbSB0aGUgYW5hbHlzaXMgCnN1aWNpZGVfZGYgJT4lIAogIGZpbHRlcihpcy5uYShgQWdlLXN0YW5kYXJkaXplZCBzdWljaWRlIHJhdGUgLSBTZXg6IGJvdGggc2V4ZXNgKSkKYGBgCgpgYGB7cn0KIyBSZW1vdmUgdGhlIFJlZ2lvbiAvIEluY29tZSBjbGFzc2VzIGFuZCBMZXNvdGhvCnN1aWNpZGVfZGZfY291bnRyaWVzID0gc3VpY2lkZV9kZiAlPiUgCiAgZmlsdGVyKENvZGUgIT0gIjAiLCBDb2RlICE9ICJMU08iKQpgYGAKCmBgYHtyfQphdmdfY291bnRyeSA9IHN1aWNpZGVfZGZfY291bnRyaWVzICU+JSAKICBncm91cF9ieShFbnRpdHkpICU+JSAKICBzdW1tYXJpc2UoYXZnX3Blcl9jb3VudHJ5ID0gbWVhbihgQWdlLXN0YW5kYXJkaXplZCBzdWljaWRlIHJhdGUgLSBTZXg6IGJvdGggc2V4ZXNgKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhhdmdfcGVyX2NvdW50cnkpKQpgYGAgCgpgYGB7cn0KZ2dwbG90KGF2Z19jb3VudHJ5LCBhZXMoeCA9IGF2Z19wZXJfY291bnRyeSkpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBsYWJzKHggPSAiTWVhbiBTdWljaWRlIHJhdGUiLCB5ID0gIkZyZXF1ZW5jeSIsIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBtZWFuIG9mIHN1aWNpZGUgcmF0ZSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyBFeHBsb3JhdGlvbiBvZiB0aGUgSGFwcGluZXNzIERhdGFzZXQKCmBgYHtyfQojIFVzZSB0aGUgcmF3IGZpbGUgVVJMCnVybCA8LSAiaHR0cHM6Ly9naXRodWIuY29tL0FsZXhidXJrOTMvRGF0YV9XcmFuZ2xpbmdfRURBL3Jhdy9tYWluL2RhdGEvcmF3X2RhdGEvV0hSMjBfRGF0YUZvclRhYmxlMi4xLnhscyIKcmVzcG9uc2UgPC0gR0VUKHVybCkKY29udGVudCA8LSBjb250ZW50KHJlc3BvbnNlLCAicmF3IikKdGVtcCA8LSB0ZW1wZmlsZShmaWxlZXh0ID0gIi54bHMiKQp3cml0ZUJpbihjb250ZW50LCB0ZW1wKQpoYXBwaW5lc3NfZGYgPC0gcmVhZF9leGNlbCh0ZW1wKQoKIyBWaWV3IHRoZSBkYXRhCmhlYWQoaGFwcGluZXNzX2RmKQoKYGBgCmBgYHtyfQojIGNyZWF0ZSBkYXRhIGZyYW1lIHdpdGggc2VsZWN0ZWQgY29sdW1ucy4gQmFzZWQgb24gdGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBkaWZmZXJlbnQgdmFyaWFibGVzLgpoYXBwaW5lc3NfZGZfZmlsdGVyZWQgPSBoYXBwaW5lc3NfZGYgJT4lIAogIHNlbGVjdChgQ291bnRyeSBuYW1lYCwgYHllYXJgICwgYExpZmUgTGFkZGVyYCwgYFNvY2lhbCBzdXBwb3J0YCwgYEhlYWx0aHkgbGlmZSBleHBlY3RhbmN5IGF0IGJpcnRoYCwgYEZyZWVkb20gdG8gbWFrZSBsaWZlIGNob2ljZXNgLCBgUGVyY2VwdGlvbnMgb2YgY29ycnVwdGlvbmApCgpzdW1tYXJ5KGhhcHBpbmVzc19kZl9maWx0ZXJlZCkKYGBgCgpgYGB7cn0KYXZnX2hhcHBpbmVzc19wZXJfY291bnRyeSA9IGhhcHBpbmVzc19kZl9maWx0ZXJlZCAlPiUgCiAgZ3JvdXBfYnkoYENvdW50cnkgbmFtZWApICU+JSAKICBzdW1tYXJpc2UoYXZnX2hhcHBpbmVzcyA9IG1lYW4oYExpZmUgTGFkZGVyYCkpICU+JSAKICBhcnJhbmdlKGRlc2MoYXZnX2hhcHBpbmVzcykpCmBgYAoKYGBge3J9CmdncGxvdChhdmdfaGFwcGluZXNzX3Blcl9jb3VudHJ5LCBhZXMoeCA9IGF2Z19oYXBwaW5lc3MpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgbGFicyh4ID0gIk1lYW4gSGFwcGluZXNzIExldmVsIiwgeSA9ICJGcmVxdWVuY3kiLCB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgbWVhbiBvZiBoYXBwaW5lc3MgcmF0ZSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyBEYXRhIGZvciBGaW5hbCBQcmVzZW50YXRpb24KCgpIYXBwaW5lc3MgRGF0YSBmb3IgdGhlIDE5IGNvdW50cmllcyBvZiBpbnRlcmVzdCBmcm9tIDIwMTEgLSAyMDE5CmBgYHtyfQojIERlZmluZSB0aGUgbGlzdCBvZiAxOSBjb3VudHJpZXMKY291bnRyaWVzX29mX2ludGVyZXN0IDwtIGMoIkF1c3RyYWxpYSIsICJCZWxnaXVtIiwgIkJyYXppbCIsICJDYW5hZGEiLCAiRGVubWFyayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJGaW5sYW5kIiwgIkZyYW5jZSIsICJHZXJtYW55IiwgIkljZWxhbmQiLCAiSXRhbHkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiSmFwYW4iLCAiTmV0aGVybGFuZHMiLCAiTmV3IFplYWxhbmQiLCAiTm9yd2F5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJTb3V0aCBBZnJpY2EiLCAiU3BhaW4iLCAiU3dlZGVuIiwgIlVuaXRlZCBLaW5nZG9tIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbml0ZWQgU3RhdGVzIikKCiMgRmlsdGVyIHRoZSBkYXRhIGZvciB0aGUgMTkgY291bnRyaWVzCmhhcHBpbmVzc19uZXc8LSBoYXBwaW5lc3NfZGZfZmlsdGVyZWQgJT4lCiAgZmlsdGVyKGBDb3VudHJ5IG5hbWVgICVpbiUgY291bnRyaWVzX29mX2ludGVyZXN0KQoKIyBEZWZpbmUgdGhlIGRhdGUgcmFuZ2Ugb2YgZm9jdXMKc3RhcnRfeWVhciA8LSAyMDExCmVuZF95ZWFyIDwtIDIwMjAKCiMgRmlsdGVyIHRoZSBkYXRhIGZvciB0aGUgZGF0ZSByYW5nZQpoYXBwaW5lc3NfZGF0YSA8LSBoYXBwaW5lc3NfbmV3ICU+JQogIGZpbHRlcihhcy5udW1lcmljKHllYXIpID49IHN0YXJ0X3llYXIgJiBhcy5udW1lcmljKHllYXIpIDw9IGVuZF95ZWFyKQoKIyBTaG93IHRoZSBmaWx0ZXJlZCBkYXRhCmhhcHBpbmVzc19kYXRhICU+JSAKICBzYW1wbGVfbigxMCkKYGBgCgpgYGB7cn0KIyBDaGVjayBpZiBhbGwgY291bnRyaWVzIG9mIGludGVyZXN0IGFyZSBwcmVzZW50IGluIHRoZSBmaWx0ZXJlZCBkYXRhCm1pc3NpbmdfY291bnRyaWVzIDwtIHNldGRpZmYoY291bnRyaWVzX29mX2ludGVyZXN0LCB1bmlxdWUoaGFwcGluZXNzX2RhdGEkYENvdW50cnkgbmFtZWApKQoKIyBQcmludCB0aGUgbWlzc2luZyBjb3VudHJpZXMsIGlmIGFueQppZihsZW5ndGgobWlzc2luZ19jb3VudHJpZXMpID4gMCkgewogIHByaW50KCJUaGUgZm9sbG93aW5nIGNvdW50cmllcyBhcmUgbWlzc2luZyBmcm9tIHRoZSBmaWx0ZXJlZCBkYXRhOiIpCiAgcHJpbnQobWlzc2luZ19jb3VudHJpZXMpCn0gZWxzZSB7CiAgcHJpbnQoIkFsbCBjb3VudHJpZXMgb2YgaW50ZXJlc3QgYXJlIHNlbGVjdGVkIGZyb20gdGhlIGZpbHRlcmVkIGRhdGEuIikKfQoKYGBgCgpgYGB7cn0KIyBDb3VudCB0aGUgb2NjdXJyZW5jZXMgb2YgZWFjaCBjb3VudHJ5IGluIHRoZSBmaWx0ZXJlZCBkYXRhCmNvdW50cnlfY291bnRzIDwtIHRhYmxlKGhhcHBpbmVzc19kYXRhJGBDb3VudHJ5IG5hbWVgKQoKIyBQcmludCB0aGUgY291bnRyeSBuYW1lcyBhbmQgdGhlaXIgY291bnRzCnByaW50KCJDb3VudHJ5IE5hbWVcdFx0Q291bnQiKQpmb3IgKGNvdW50cnkgaW4gbmFtZXMoY291bnRyeV9jb3VudHMpKSB7CiAgY2F0KGNvdW50cnksICJcdFx0XHQiLCBjb3VudHJ5X2NvdW50c1tjb3VudHJ5XSwgIlxuIikKfQoKYGBgCgpTdWljaWRlIERhdGEgZm9yIHRoZSAxOSBjb3VudHJpZXMgb2YgaW50ZXJlc3QgZnJvbSAyMDExIC0gMjAxOQpgYGB7cn0KIyBDaGFuZ2UgY29sdW1uIG5hbWUgZnJvbSBgRW50aXR5YCB0byBgY291bnRyeSBuYW1lYApzdWljaWRlX2RmIDwtIHJlbmFtZShzdWljaWRlX2RmLCBgQ291bnRyeSBuYW1lYCA9IEVudGl0eSkKCiMgRGVmaW5lIHRoZSBsaXN0IG9mIDE5IGNvdW50cmllcwpjb3VudHJpZXNfb2ZfaW50ZXJlc3QgPC0gYygiQXVzdHJhbGlhIiwgIkJlbGdpdW0iLCAiQnJhemlsIiwgIkNhbmFkYSIsICJEZW5tYXJrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZpbmxhbmQiLCAiRnJhbmNlIiwgIkdlcm1hbnkiLCAiSWNlbGFuZCIsICJJdGFseSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJKYXBhbiIsICJOZXRoZXJsYW5kcyIsICJOZXcgWmVhbGFuZCIsICJOb3J3YXkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNvdXRoIEFmcmljYSIsICJTcGFpbiIsICJTd2VkZW4iLCAiVW5pdGVkIEtpbmdkb20iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVuaXRlZCBTdGF0ZXMiKQoKIyBGaWx0ZXIgdGhlIGRhdGEgZm9yIHRoZSAxOSBjb3VudHJpZXMKbmV3X3N1aWNpZGU8LSBzdWljaWRlX2RmICU+JQogIGZpbHRlcihgQ291bnRyeSBuYW1lYCAlaW4lIGNvdW50cmllc19vZl9pbnRlcmVzdCkKCiMgRGVmaW5lIHRoZSBkYXRlIHJhbmdlIG9mIGZvY3VzCnN0YXJ0X3llYXIgPC0gMjAxMQplbmRfeWVhciA8LSAyMDIwCgojIEZpbHRlciB0aGUgZGF0YSBmb3IgdGhlIGRhdGUgcmFuZ2UKc3VpY2lkZV9kYXRhIDwtIG5ld19zdWljaWRlICU+JQogIGZpbHRlcihhcy5udW1lcmljKFllYXIpID49IHN0YXJ0X3llYXIgJiBhcy5udW1lcmljKFllYXIpIDw9IGVuZF95ZWFyKQoKIyBTaG93IHRoZSBmaWx0ZXJlZCBkYXRhCnN1aWNpZGVfZGF0YSAlPiUgCiAgc2FtcGxlX24oMTApCmBgYAoKIyMgUHJpbnQgYWxsIHRoZSBkYXRhIHNldHMKCmBgYHtyfQpzdWljaWRlX2RhdGEgJT4lIAogIHNhbXBsZV9uKDEwKQoKaGFwcGluZXNzX2RhdGEgJT4lIAogIHNhbXBsZV9uKDEwKQoKZ2RwICU+JSAKICBzYW1wbGVfbigxMCkKCmJhbmtydXB0Y3lfZGF0YSAlPiUgCiAgc2FtcGxlX24oMTApCmBgYAoKCiMjIExhYmVsIGhlYWRlcnMgdG8gYWxpZ24gYWxsIHRoZSBkYXRhIHNldCAmIHZpZXcgc2FtcGxlIGRhdGEKYGBge3J9CmdkcApiYW5rcnVwdGN5X2RhdGEKYGBgCgoKYGBge3J9CiMgQ2hhbmdlIGNvbHVtbiBuYW1lIGZyb20gYEVudGl0eWAgdG8gYGNvdW50cnkgbmFtZWAKZ2RwX2RhdGEgPC0gcmVuYW1lKGdkcCwgYENvdW50cnkgbmFtZWAgPSBgQ291bnRyeSBOYW1lYCkKYmFua3J1cHRjeV9kYXRhPC0gcmVuYW1lKGJhbmtydXB0Y3lfZGF0YSwgYENvdW50cnkgbmFtZWAgPSBgQ291bnRyeWApCmhhcHBpbmVzc19kYXRhID0gcmVuYW1lKGhhcHBpbmVzc19kYXRhLCBgWWVhcmAgPSBgeWVhcmApCnN1aWNpZGVfZGF0YSAlPiUgCiAgc2FtcGxlX24oMTApCgpoYXBwaW5lc3NfZGF0YSAlPiUgCiAgc2FtcGxlX24oMTApCgpnZHBfZGF0YSAlPiUgCiAgc2FtcGxlX24oMTApCgpiYW5rcnVwdGN5X2RhdGEgJT4lIAogIHNhbXBsZV9uKDEwKQpgYGAKIyMgTWVyZ2luZyBkYXRhc2V0cwoKYGBge3J9CmdkcF9kYXRhCmhhcHBpbmVzc19kYXRhCmJhbmtydXB0Y3lfZGF0YQpzdWljaWRlX2RhdGEKYGBgCgpgYGB7cn0KIyBDb252ZXJ0ICJZZWFyIiBjb2x1bW4gdG8gY2hhcmFjdGVyIHR5cGUgaW4gYWxsIGRhdGFzZXRzCnN1aWNpZGVfZGF0YSA8LSBtdXRhdGUoc3VpY2lkZV9kYXRhLCBZZWFyID0gYXMuY2hhcmFjdGVyKFllYXIpKQpoYXBwaW5lc3NfZGF0YSA8LSBtdXRhdGUoaGFwcGluZXNzX2RhdGEsIFllYXIgPSBhcy5jaGFyYWN0ZXIoWWVhcikpCmdkcF9kYXRhIDwtIG11dGF0ZShnZHBfZGF0YSwgWWVhciA9IGFzLmNoYXJhY3RlcihZZWFyKSkKYmFua3J1cHRjeV9kYXRhIDwtIG11dGF0ZShiYW5rcnVwdGN5X2RhdGEsIFllYXIgPSBhcy5jaGFyYWN0ZXIoWWVhcikpCgojIE1lcmdlIHRoZSBkYXRhc2V0cwpzdWljaWRlX2FuYWx5c2lzIDwtIHN1aWNpZGVfZGF0YSAlPiUKICBsZWZ0X2pvaW4oaGFwcGluZXNzX2RhdGEsIGJ5ID0gYygiWWVhciIsICJDb3VudHJ5IG5hbWUiKSkgJT4lCiAgbGVmdF9qb2luKGdkcF9kYXRhLCBieSA9IGMoIlllYXIiLCAiQ291bnRyeSBuYW1lIikpICU+JQogIGxlZnRfam9pbihiYW5rcnVwdGN5X2RhdGEsIGJ5ID0gYygiWWVhciIsICJDb3VudHJ5IG5hbWUiKSkKCmBgYApgYGB7cn0KIyBWaWV3IHNhbXBsZSBkYXRhIGZyb20gdGhlIG1lcmdlZCBkYXRhc2V0CnN1aWNpZGVfYW5hbHlzaXMgCmBgYAoKU2F2ZSB0aGUgZGF0YXNldCBpbiBleGNlbCBjc3YgZm9ybWF0IHRvIHJ1biBhbmFseXNpcyBmb3IgdGhlIGZpbmFsIHByb2plY3QKYGBge3J9CgojICMgRHJvcCBzcGVjaWZpZWQgY29sdW1ucwojIHN1aWNpZGVfYW5hbHlzaXMgPC0gc3VpY2lkZV9hbmFseXNpcyAlPiUKIyAgIHNlbGVjdCgtYygiQ29kZSIsICJDT1UiLCAiUG93ZXJDb2RlIiwgIlBvd2VyQ29kZSBDb2RlIikpCiMgCiMgIyBTYXZlIHRoZSBtZXJnZWQgZGF0YXNldCBhcyBhIENTViBmaWxlCiMgIyBEZWZpbmUgdGhlIHBhdGggdG8gdGhlIGZvbGRlciBvbiB5b3VyIGRlc2t0b3AKIyBkZXNrdG9wX3BhdGggPC0gIi9ob21lL2FsZXgvVW5pL01hc3Rlcl9VUy8yX1NlbWVzdGVyL0NsYXNzX0RhdGFfV3JhbmdlbGluZ19FREEvRGF0YV9XcmFuZ2xpbmdfRURBL2RhdGEvIgojIAojICMgQ3JlYXRlIHRoZSBmb2xkZXIgaWYgaXQgZG9lc24ndCBleGlzdAojIGRpci5jcmVhdGUoZGVza3RvcF9wYXRoLCBzaG93V2FybmluZ3MgPSBGQUxTRSkKIyAKIyAjIFNhdmUgdGhlIG1lcmdlZCBkYXRhc2V0IGFzIGEgQ1NWIGZpbGUgaW4gdGhlIHNwZWNpZmllZCBmb2xkZXIKIyB3cml0ZS5jc3Yoc3VpY2lkZV9hbmFseXNpcywgZmlsZS5wYXRoKGRlc2t0b3BfcGF0aCwgInN1aWNpZGVfYW5hbHlzaXNfMi5jc3YiKSwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoaGlnaGNoYXJ0ZXIpCmxpYnJhcnkobWFncml0dHIpCmBgYAojIEVEQQojIyBEYXRhIGxvYWRpbmcKYGBge3J9CmRhdGEgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9BbGV4YnVyazkzL0RhdGFfV3JhbmdsaW5nX0VEQS9tYWluL2RhdGEvc3VpY2lkZV9hbmFseXNpc18yLmNzdiIpCiAgICAgICAgICAgICAgICBkYXRhICU+JSBzYW1wbGVfbigxOSkKYGBgCiMjIFJlbmFtaW5nIHZhcmlhYmxlcyBhbmQgZHJvcCB1bndhbnRlZCBjb2x1bW5zCmBgYHtyfQojIHJlbmFtaW5nIHRoZSBjb2x1bW5zIApkYXRhIDwtIGRhdGEgJT4lCiAgcmVuYW1lKGBDb3VudHJ5X25hbWVgID0gYENvdW50cnkgbmFtZWAsCiAgICAgICAgIGBTdWljaWRlX1JhdGVgID0gYEFnZS1zdGFuZGFyZGl6ZWQgc3VpY2lkZSByYXRlIC0gU2V4OiBib3RoIHNleGVzYCwKICAgICAgICAgYExpZmVfbGFkZGVyYCA9IGBMaWZlIExhZGRlcmAsCiAgICAgICAgIGBTb2NpYWxfc3VwcG9ydGAgPSBgU29jaWFsIHN1cHBvcnRgLAogICAgICAgICBgTGlmZV9leHBlY3RhbmN5YCA9IGBIZWFsdGh5IGxpZmUgZXhwZWN0YW5jeSBhdCBiaXJ0aGAsCiAgICAgICAgIGBGcmVlZG9tX2Nob2ljZXNgID0gYEZyZWVkb20gdG8gbWFrZSBsaWZlIGNob2ljZXNgLAogICAgICAgICBgQ29ycnVwdGlvbmAgPSBgUGVyY2VwdGlvbnMgb2YgY29ycnVwdGlvbmApCmBgYAoKYGBge3J9CmRhdGEKYGBgCmBgYHtyfQpkYXRhCmBgYAoKCmBgYHtyfQojIGRyb3AgY29sdW1ucyAKIyByZW1vdmUgdGhlIG9yaWdpbmFsICdUaW1lJyBjb2x1bW4KZGF0YSA8LSBzZWxlY3QoZGF0YSwgLVZhcmlhYmxlLCAtVkFSLCAtTUVBLCAtYFVuaXQgQ29kZWApICAKZGF0YQpgYGAKCiMjIERhdGEgZXhwbG9yYXRpb24KYGBge3J9CmhlYWQoZGF0YSkKYGBgCgpgYGB7cn0KIyBjaGFuZ2UgbmFtZXMKbmFtZXMoZGF0YSkgPC0gbWFrZS5uYW1lcyhuYW1lcyhkYXRhKSkKYGBgCgpgYGB7cn0KIyBkaW1lbnNpb25zIG9mIHRoZSBkYXRhZnJhbWUKbnJvdyhkYXRhKQpuY29sKGRhdGEpCmRpbShkYXRhKQpgYGAKCmBgYHtyfQojIGNoZWNrIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIG9iamVjdApzdHIoZGF0YSkKYGBgCmBgYHtyfQojIGxvb2sgYXQgY29sdW1ucyA2LCA3IGFuZCAxMApoZWFkKGRhdGFbICwgYygyLCA0OjYsIDEyLCAxNSldKQpgYGAKCmBgYHtyfQojIGxvb2sgYXQgY29sdW1ucyA2LCA3IGFuZCAxMAp0YWlsKGRhdGFbICwgYygxLCAzLCA5KV0pCmBgYAoKYGBge3J9CnRhYmxlKGRhdGEkWWVhcikKYGBgCgoKYGBge3J9CmRhdGEgJT4lIAogIHNlbGVjdChDb3VudHJ5X25hbWUpICU+JSAKICB1bmlxdWUoKSAlPiUgCiAgbnJvdygpCmBgYAoKYGBge3J9CnVuaXF1ZShkYXRhJENvdW50cnlfbmFtZSkKYGBgCgpgYGB7cn0KdW5pcXVlKGRhdGEkWWVhcikKYGBgCgojIyBJbnRlcmFjdGl2ZSBtYXBzCmBgYHtyfQojIFNldCBoaWdoY2hhcnRlciBvcHRpb25zIGZvciB0b29sdGlwIGRlY2ltYWxzCm9wdGlvbnMoaGlnaGNoYXJ0ZXIudG9vbHRpcC52YWx1ZURlY2ltYWxzID0gMikKCiMgQ3JlYXRlIGhpZ2hjaGFydGVyIG1hcCB2aXN1YWxpemF0aW9uCmhjIDwtIGhpZ2hjaGFydCgpICU+JQogIGhjX2FkZF9zZXJpZXNfbWFwKAogICAgd29ybGRnZW9qc29uLCBkYXRhLCB2YWx1ZSA9ICJHRFAiLCAKICAgIGpvaW5CeSA9IGMoJ25hbWUnLCAnQ291bnRyeV9uYW1lJyksCiAgICBuYW1lID0gIkdEUCAoY3VycmVudCBVUyQpIgogICkgICU+JSAKICBoY19jb2xvckF4aXMoc3RvcHMgPSBjb2xvcl9zdG9wcygpKSAlPiUgCiAgaGNfdGl0bGUodGV4dCA9ICJXb3JsZCBNYXAiKSAlPiUgCiAgaGNfc3VidGl0bGUodGV4dCA9ICJHRFAgaW4gY3VycmVudCBVUyQiKQoKaGMKYGBgCgpgYGB7cn0KIyBTZXQgaGlnaGNoYXJ0ZXIgb3B0aW9ucyBmb3IgdG9vbHRpcCBkZWNpbWFscwpvcHRpb25zKGhpZ2hjaGFydGVyLnRvb2x0aXAudmFsdWVEZWNpbWFscyA9IDIpCgojIENyZWF0ZSBtYXAgdmlzdWFsaXphdGlvbnMgZm9yIGVhY2ggdmFyaWFibGUKaGNfbGlmZV9leHBlY3RhbmN5IDwtIGhpZ2hjaGFydCgpICU+JQogIGhjX2FkZF9zZXJpZXNfbWFwKAogICAgd29ybGRnZW9qc29uLCBkYXRhLCAKICAgIHZhbHVlID0gIkxpZmVfZXhwZWN0YW5jeSIsIAogICAgam9pbkJ5ID0gYygnbmFtZScsICdDb3VudHJ5X25hbWUnKSwKICAgIG5hbWUgPSAiTGlmZSBFeHBlY3RhbmN5IgogICkgJT4lCiAgaGNfY29sb3JBeGlzKHN0b3BzID0gY29sb3Jfc3RvcHMoKSkgJT4lCiAgaGNfdGl0bGUodGV4dCA9ICJXb3JsZCBNYXAiKSAlPiUKICBoY19zdWJ0aXRsZSh0ZXh0ID0gIkxpZmUgRXhwZWN0YW5jeSIpCgpoY19zdWljaWRlX3JhdGVzIDwtIGhpZ2hjaGFydCgpICU+JQogIGhjX2FkZF9zZXJpZXNfbWFwKAogICAgd29ybGRnZW9qc29uLCBkYXRhLCAKICAgIHZhbHVlID0gIlN1aWNpZGVfUmF0ZSIsIAogICAgam9pbkJ5ID0gYygnbmFtZScsICdDb3VudHJ5X25hbWUnKSwKICAgIG5hbWUgPSAiU3VpY2lkZSBSYXRlcyIKICApICU+JQogIGhjX2NvbG9yQXhpcyhzdG9wcyA9IGNvbG9yX3N0b3BzKCkpICU+JQogIGhjX3RpdGxlKHRleHQgPSAiV29ybGQgTWFwIikgJT4lCiAgaGNfc3VidGl0bGUodGV4dCA9ICJTdWljaWRlIFJhdGUiKQoKaGNfY29ycnVwdGlvbiA8LSBoaWdoY2hhcnQoKSAlPiUKICBoY19hZGRfc2VyaWVzX21hcCgKICAgIHdvcmxkZ2VvanNvbiwgZGF0YSwgCiAgICB2YWx1ZSA9ICJDb3JydXB0aW9uIiwgCiAgICBqb2luQnkgPSBjKCduYW1lJywgJ0NvdW50cnlfbmFtZScpLAogICAgbmFtZSA9ICJDb3JydXB0aW9uIgogICkgJT4lCiAgaGNfY29sb3JBeGlzKHN0b3BzID0gY29sb3Jfc3RvcHMoKSkgJT4lCiAgaGNfdGl0bGUodGV4dCA9ICJXb3JsZCBNYXAiKSAlPiUKICBoY19zdWJ0aXRsZSh0ZXh0ID0gIkNvcnJ1cHRpb24iKQoKIyBEaXNwbGF5IHRoZSBtYXAgdmlzdWFsaXphdGlvbnMKbGlzdChoY19saWZlX2V4cGVjdGFuY3ksIGhjX3N1aWNpZGVfcmF0ZXMsIGhjX2NvcnJ1cHRpb24pCgpgYGAKIyBBbmFseXNpcyAKIyMgQVZHIEdEUCBvdmVyIHllYXJzCiMjIyBDYWxjdWxhdGlvbiAKYGBge3J9CmF2Z19nZHBfcGVyX3llYXIgPC0gZGF0YSAlPiUgCiAgZ3JvdXBfYnkgKGBZZWFyYCkgJT4lIAogIHN1bW1hcmlzZShhdmdfZ3BkID0gbWVhbihgR0RQYCkpCgphdmdfZ2RwX3Blcl95ZWFyCmBgYAojIyMgUGxvdCAKYGBge3J9CmdncGxvdChhdmdfZ2RwX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfZ3BkKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEdEUCBPdmVyIFRpbWUgd29ybGR3aWRlIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkdEUCIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfZ2RwX3Blcl95ZWFyJFllYXIpLCBtYXgoYXZnX2dkcF9wZXJfeWVhciRZZWFyKSwgYnkgPSAxKSkKYGBgCiMjIEFWRyBIYXBwaW5lc3Mgb3ZlciB5ZWFycwojIyMgQ2FsY3VsYXRpb24gCmBgYHtyfQphdmdfaGFwcGluZXNzX3Blcl95ZWFyIDwtIGRhdGEgJT4lIAogIGdyb3VwX2J5IChgWWVhcmApICU+JSAKICBzdW1tYXJpc2UoYXZnX2hhcHBpbm5lcyA9IG1lYW4oYExpZmVfbGFkZGVyYCwgbmEucm0gPSBUKSkKCmF2Z19oYXBwaW5lc3NfcGVyX3llYXIKYGBgCiMjIyBQbG90IAoKYGBge3J9CmdncGxvdChhdmdfaGFwcGluZXNzX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfaGFwcGlubmVzKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEhhcHBpbmVzcyBPdmVyIFRpbWUgd29ybGR3aWRlIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkhhcHBpbmVzcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfaGFwcGluZXNzX3Blcl95ZWFyJFllYXIpLCBtYXgoYXZnX2hhcHBpbmVzc19wZXJfeWVhciRZZWFyKSwgYnkgPSAxKSkKYGBgCgojIyBBVkcgU3VpY2lkZSBSYXRlcyBvdmVyIHllYXJzCiMjIyBDYWxjdWxhdGlvbiAKYGBge3J9CmF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIgPC0gZGF0YSAlPiUgCiAgZ3JvdXBfYnkgKGBZZWFyYCkgJT4lIAogIHN1bW1hcmlzZShhdmdfU3VpY2lkZV9SYXRlID0gbWVhbihgU3VpY2lkZV9SYXRlYCwgbmEucm0gPSBUKSkKCmF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIKYGBgCiMjIyBQbG90IAoKYGBge3J9CmdncGxvdChhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfU3VpY2lkZV9SYXRlKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUgd29ybGR3aWRlIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIlN1aWNpZGUgUmF0ZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpLCBtYXgoYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRZZWFyKSwgYnkgPSAxKSkKYGBgCiMjIEFWRyBCYW5rcnVwdGNpZXMgb3ZlciB5ZWFycwojIyMgQ2FsY3VsYXRpb24gCmBgYHtyfQphdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyIDwtIGRhdGEgJT4lIAogIGdyb3VwX2J5IChgWWVhcmApICU+JSAKICBzdW1tYXJpc2UoYXZnX0JhbmtydXB0Y2llcyA9IG1lYW4oYFZhbHVlYCwgbmEucm0gPSBUKSkKCmF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIKYGBgCiMjIyBQbG90IAoKYGBge3J9CmdncGxvdChhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfQmFua3J1cHRjaWVzKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEJhbmtydXB0Y2llcyBPdmVyIFRpbWUgd29ybGR3aWRlIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkJhbmtydXB0Y2llcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyJFllYXIpLCBtYXgoYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciRZZWFyKSwgYnkgPSAxKSkKYGBgCgojIyBQbG90IEF2ZXJhZ2UgR0RQIGFuZCBBdmVyYWdlIFN1aWNpZGUgUmF0ZSBvdmVyIHllYXJzCmBgYHtyfQojIEZpbmRpbmcgdGhlIHJhdGlvIGZvciBzY2FsaW5nIHRoZSBzZWNvbmQgYXhpcwpyYXRpbyA8LSBtYXgoYXZnX2dkcF9wZXJfeWVhciRhdmdfZ3BkKSAvIG1heChhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJGF2Z19TdWljaWRlX1JhdGUpCgojIENyZWF0aW5nIHRoZSBiYXNlIHBsb3QKZ2dwbG90KCkgKwogICMgQWRkaW5nIHRoZSBiYXIgcGxvdCBmb3IgR0RQCiAgZ2VvbV9saW5lKGRhdGEgPSBhdmdfZ2RwX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfZ3BkKSwgc2l6ZSA9IDAuNSkgKwogICMgQWRkaW5nIHRoZSBsaW5lIHBsb3QgZm9yIEF2ZXJhZ2UgSGFwcGluZXNzCiAgZ2VvbV9saW5lKGRhdGEgPSBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfU3VpY2lkZV9SYXRlICogcmF0aW8pLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMC41KSArCiAgIyBFbmhhbmNpbmcgdGhlIHBsb3QKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgR0RQIGFuZCBTdWljaWRlIFJhdGUgT3ZlciBUaW1lIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkF2ZXJhZ2UgR0RQIikgKwogIHNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvIHJhdGlvLCBuYW1lID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihjKGF2Z19nZHBfcGVyX3llYXIkWWVhciwgYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRZZWFyKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGMoYXZnX2dkcF9wZXJfeWVhciRZZWFyLCBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpKSwgYnkgPSAxKSkKCmBgYAoKIyMgUGxvdCBBdmVyYWdlIEhhcHBpbm5lc3MgYW5kIEF2ZXJhZ2UgU3VpY2lkZSBSYXRlIG92ZXIgeWVhcnMKYGBge3J9CiMgRmluZGluZyB0aGUgcmF0aW8gZm9yIHNjYWxpbmcgdGhlIHNlY29uZCBheGlzCnJhdGlvIDwtIG1heChhdmdfaGFwcGluZXNzX3Blcl95ZWFyJGF2Z19oYXBwaW5uZXMpIC8gbWF4KGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkYXZnX1N1aWNpZGVfUmF0ZSkKCiMgQ3JlYXRpbmcgdGhlIGJhc2UgcGxvdApnZ3Bsb3QoKSArCiAgIyBBZGRpbmcgdGhlIGJhciBwbG90IGZvciBHRFAKICBnZW9tX2xpbmUoZGF0YSA9IGF2Z19oYXBwaW5lc3NfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19oYXBwaW5uZXMpLCBzaXplID0gMC41KSArCiAgIyBBZGRpbmcgdGhlIGxpbmUgcGxvdCBmb3IgQXZlcmFnZSBIYXBwaW5lc3MKICBnZW9tX2xpbmUoZGF0YSA9IGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19TdWljaWRlX1JhdGUgKiByYXRpbyksIGNvbG9yID0gInJlZCIsIHNpemUgPSAwLjUpICsKICAjIEVuaGFuY2luZyB0aGUgcGxvdAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBIYXBwaW5uZXNzIGFuZCBTdWljaWRlIFJhdGUgT3ZlciBUaW1lIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkF2ZXJhZ2UgSGFwcGlubmVzcyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoc2VjLmF4aXMgPSBzZWNfYXhpcyh+IC4gLyByYXRpbywgbmFtZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYyhhdmdfaGFwcGluZXNzX3Blcl95ZWFyJFllYXIsIGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkWWVhcikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChjKGF2Z19oYXBwaW5lc3NfcGVyX3llYXIkWWVhciwgYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRZZWFyKSksIGJ5ID0gMSkpCgpgYGAKYGBge3J9CiMgRmluZGluZyB0aGUgcmF0aW8gZm9yIHNjYWxpbmcgdGhlIHNlY29uZCBheGlzCnJhdGlvIDwtIG1heChhdmdfaGFwcGluZXNzX3Blcl95ZWFyJGF2Z19oYXBwaW5uZXMpIC8gbWF4KGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkYXZnX1N1aWNpZGVfUmF0ZSkKCiMgQ3JlYXRpbmcgdGhlIGJhc2UgcGxvdApnZ3Bsb3QoKSArCiAgIyBBZGRpbmcgdGhlIGxpbmUgcGxvdCBmb3IgQXZlcmFnZSBIYXBwaW5lc3MKICBnZW9tX2xpbmUoZGF0YSA9IGF2Z19oYXBwaW5lc3NfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19oYXBwaW5uZXMpLCBzaXplID0gMC41KSArCiAgIyBBZGRpbmcgdGhlIGxpbmUgcGxvdCBmb3IgU3VpY2lkZSBSYXRlIGFkanVzdGVkIGJ5IHRoZSByYXRpbwogIGdlb21fbGluZShkYXRhID0gYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX1N1aWNpZGVfUmF0ZSAqIHJhdGlvKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDAuNSkgKwogICMgU2V0dGluZyB1cCB0aGUgdGl0bGVzIGFuZCBsYWJlbHMKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgSGFwcGluZXNzIGFuZCBTdWljaWRlIFJhdGUgT3ZlciBUaW1lIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkF2ZXJhZ2UgSGFwcGluZXNzIiwKICAgICAgIHN1YnRpdGxlID0gIlN1aWNpZGUgcmF0ZXMgYXJlIHNjYWxlZCB0byBjb21wYXJlIGFnYWluc3QgaGFwcGluZXNzIikgKwogICMgUHJpbWFyeSBheGlzIGZvciBIYXBwaW5lc3MsIHNlY29uZGFyeSBheGlzIGZvciBTdWljaWRlIFJhdGUgKGludmVyc2VkIHNjYWxpbmcpCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQXZlcmFnZSBIYXBwaW5lc3MiLAogICAgICAgICAgICAgICAgICAgICBzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvIHJhdGlvLCBuYW1lID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIikpICsKICAjIE1pbmltYWxpc3QgdGhlbWUgd2l0aCBhbmdsZWQgeC1heGlzIHRleHRzCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgIyBTZXQgeC1heGlzIGJyZWFrcwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGMoYXZnX2hhcHBpbmVzc19wZXJfeWVhciRZZWFyLCBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoYyhhdmdfaGFwcGluZXNzX3Blcl95ZWFyJFllYXIsIGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkWWVhcikpLCBieSA9IDEpKQoKYGBgCgojIyBQbG90IEF2ZXJhZ2UgQmFua3J1cHRjaWVzIGFuZCBBdmVyYWdlIFN1aWNpZGUgUmF0ZSBvdmVyIHllYXJzCmBgYHtyfQojIEZpbmRpbmcgdGhlIHJhdGlvIGZvciBzY2FsaW5nIHRoZSBzZWNvbmQgYXhpcwpyYXRpbyA8LSBtYXgoYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciRhdmdfQmFua3J1cHRjaWVzKSAvIG1heChhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJGF2Z19TdWljaWRlX1JhdGUpCgojIENyZWF0aW5nIHRoZSBiYXNlIHBsb3QKZ2dwbG90KCkgKwogICMgQWRkaW5nIHRoZSBiYXIgcGxvdCBmb3IgR0RQCiAgZ2VvbV9saW5lKGRhdGEgPSBhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfQmFua3J1cHRjaWVzKSwgc2l6ZSA9IDAuNSkgKwogICMgQWRkaW5nIHRoZSBsaW5lIHBsb3QgZm9yIEF2ZXJhZ2UgSGFwcGluZXNzCiAgZ2VvbV9saW5lKGRhdGEgPSBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfU3VpY2lkZV9SYXRlICogcmF0aW8pLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMC41KSArCiAgIyBFbmhhbmNpbmcgdGhlIHBsb3QKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgQmFua3J1cHRjaWVzIGFuZCBTdWljaWRlIFJhdGUgT3ZlciBUaW1lIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkF2ZXJhZ2UgQmFua3J1cHRjaWVzIikgKwogIHNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvIHJhdGlvLCBuYW1lID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihjKGF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIkWWVhciwgYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRZZWFyKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGMoYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciRZZWFyLCBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpKSwgYnkgPSAxKSkKCmBgYAoKIyMgQ29tcGFyaXNpb25zCgojIyBUd28gSGFwcGllc3QgYW5kIFR3byB1bmhhcHBpZXN0IGNvdW50cmllcyB2cyBhdmVyYWdlIHN1aWNpZGUgcmF0ZQpgYGB7cn0KYXZnX1N1aWNpZGVfUmF0ZV9wZXJfY291bnRyeSA9IGRhdGEgJT4lCiAgZ3JvdXBfYnkoQ291bnRyeV9uYW1lKSAlPiUKICBzdW1tYXJpc2UoYXZnX3N1aWNpZGVfcmF0ZSA9IG1lYW4oU3VpY2lkZV9SYXRlLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBhcnJhbmdlKGF2Z19zdWljaWRlX3JhdGUpICU+JSAKICBtdXRhdGUoUm93X051bWJlciA9IHJvd19udW1iZXIoKSkKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkKCmF2Z19oYXBwaW5lc3NfcGVyX2NvdW50cnkgPC0gZGF0YSAlPiUKICBncm91cF9ieShDb3VudHJ5X25hbWUpICU+JQogIHN1bW1hcmlzZShhdmdfaGFwcGluZXNzID0gbWVhbihMaWZlX2xhZGRlciwgbmEucm0gPSBUUlVFKSkgJT4lCiAgYXJyYW5nZShkZXNjKGF2Z19oYXBwaW5lc3MpKQoKbGVhc3RfaGFwcHkgPSAgdGFpbChhdmdfaGFwcGluZXNzX3Blcl9jb3VudHJ5LCAyKQptb3N0X2hhcHB5ID0gaGVhZChhdmdfaGFwcGluZXNzX3Blcl9jb3VudHJ5LCAyKQoKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgJWluJSBsZWFzdF9oYXBweSRDb3VudHJ5X25hbWUpCgojIEludGVycHJldGF0aW9uOiBKYXBhbiBhbmQgU291dGggQWZyaWNhIGFyZSB0d28gdmVyeSB1bmhhcHB5IGNvdW50cmllcy4gQW5kIHRoZXkgYWxzbyBoYXZlIGEgaGlnaCBzdWljaWRlIHJhdGUKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgJWluJSBtb3N0X2hhcHB5JENvdW50cnlfbmFtZSkKCiMgSW50ZXJwcmV0YXRpb246IEZpbmxhbmQgaXMgYSB0aGUgc2Vjb25kIG1vc3QgaGFwcHkgY291bnRyeS4gQnV0IGlzIHN0aWxsIG9uIHBsYWNlIDE2LzE5IHdoZW4gaXQgY29tZXMgdG8gc3VpY2lkZXMKCmBgYAoKIyMjIFR3byBtb3N0IHdlYWx0aHkgY291bnRyaWVzIGFuZCB0d28gbW9zdCBwb29yIGNvdW50cmllcyB2cyBhdmVyYWdlIHN1aWNpZGUgcmF0ZQpgYGB7cn0KYXZnX2dkcF9wZXJfY291bnRyeSA8LSBkYXRhICU+JSAKICBncm91cF9ieSAoYENvdW50cnlfbmFtZWApICU+JSAKICBzdW1tYXJpc2UoYXZnX2dwZCA9IG1lYW4oYEdEUGApKSAlPiUgCiAgYXJyYW5nZShkZXNjKGF2Z19ncGQpKQoKbGVhc3RfZ2RwID0gIHRhaWwoYXZnX2dkcF9wZXJfY291bnRyeSwgMikKbW9zdF9nZHAgPSBoZWFkKGF2Z19nZHBfcGVyX2NvdW50cnksIDIpCgphdmdfU3VpY2lkZV9SYXRlX3Blcl9jb3VudHJ5ICU+JSAKICBmaWx0ZXIoQ291bnRyeV9uYW1lICVpbiUgbGVhc3RfZ2RwJENvdW50cnlfbmFtZSkKCiMgSW50ZXJwcmV0YXRpb246IEJyYXppbCB3aXRoIGEgbG93IEdQRCBwZXIgQ2FwaXRhIGlzIHN0aWxsIGxvdyBpbiB0aGUgc3VpY2lkZSByYW5raW5nLiBTQSBoYXMgYSBiYWQgR1BBIHBlciBDYXBpdGEgYW5kIGlzIGFsc28gYmFkIGluIHRoZSBzdWljaWRlIHJhbmtpbmcgIAoKYXZnX1N1aWNpZGVfUmF0ZV9wZXJfY291bnRyeSAlPiUgCiAgZmlsdGVyKENvdW50cnlfbmFtZSAlaW4lIG1vc3RfZ2RwJENvdW50cnlfbmFtZSkKCiMgSW50ZXJwcmV0YXRpb246IFRoZSB0d28gYmlnZ2VzdCBlY29ub21pZXMgYXJlIGJhc2VkIGluIHRoZSBtaWRkbGUgb2YgdGhlIHN1aWNpZGUgcmF0aW5nCmBgYAoKCiMjIFR3byBtb3N0IGJhbmtjdXB0Y2llcyBhbmQgdHdvIGxlYXN0IGJhbmtjdXB0Y2llcyBjb3VudHJpZXMgdnMgYXZlcmFnZSBzdWljaWRlIHJhdGUKYGBge3J9CmF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIgPC0gZGF0YSAlPiUgCiAgZ3JvdXBfYnkgKGBDb3VudHJ5X25hbWVgKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19iYW5rcnVwdGNpZXMgPSBtZWFuKGBWYWx1ZWAsIG5hLnJtID0gVCkpICU+JSAKICBhcnJhbmdlKGRlc2MoYXZnX2JhbmtydXB0Y2llcykpCgpsZWFzdF9iYW5rID0gIHRhaWwoYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciwgMikKbW9zdF9iYW5rID0gaGVhZChhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyLCAyKQoKYXZnX1N1aWNpZGVfUmF0ZV9wZXJfY291bnRyeSAlPiUgCiAgZmlsdGVyKENvdW50cnlfbmFtZSAlaW4lIGxlYXN0X2JhbmskQ291bnRyeV9uYW1lKQoKIyBJbnRlcnByZXRhdGlvbjogQmFua3J1cHRjaWVzIGRvbid0IGhhdmUgYW4gaW5mbHVlbmNlIG9uIHN1aWNpZGUgcmF0ZXMKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgJWluJSBtb3N0X2JhbmskQ291bnRyeV9uYW1lKQoKIyBJbnRlcnByZXRhdGlvbjogQmFua3J1cHRjaWVzIGRvbid0IGhhdmUgYW4gaW5mbHVlbmNlIG9uIHN1aWNpZGUgcmF0ZXMKYGBgCiMjIEluIGRlcHRoIGFuYWx5c2lzIEdlcm1hbnkKIyMjIERhdGEgcHJlcGVyYXRpb24gZm9yIEdlcm1hbnkKYGBge3J9CiMgUHJlcGFyZSBkYXRhIGZvciBvbmx5IEdlcm1hbnkKZ2VybWFueV9kYXRhID0gZGF0YSAlPiUgCiAgZmlsdGVyKENvdW50cnlfbmFtZSA9PSAiR2VybWFueSIpCmBgYAoKIyMjIFBsb3QgR0RQIEdlcm1hbnkKYGBge3J9CiMgUGxvdCBHZXJtYW55IEdEUCBvdmVyIFllYXJzCmF2Z19nZHBfeWVhcl9nZXJtYW55ID0gZ2VybWFueV9kYXRhICU+JSAKICBncm91cF9ieShZZWFyKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19nZHAgPSBtZWFuKEdEUCkpIAoKCmdncGxvdChhdmdfZ2RwX3llYXJfZ2VybWFueSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2dkcCkpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiYmx1ZSIpICsgIAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBHUEQgT3ZlciBUaW1lIC0gR2VybWFueSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJHRFAiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX2dkcF95ZWFyX2dlcm1hbnkkWWVhciksIG1heChhdmdfZ2RwX3llYXJfZ2VybWFueSRZZWFyKSwgYnkgPSAxKSkKCmBgYAoKIyMjIFBsb3QgU3VpY2lkZSBSYXRlIEdlcm1hbnkKYGBge3J9CmF2Z19zdWljaWRlX3llYXJfZ2VybWFueSA9IGdlcm1hbnlfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIHN1bW1hcmlzZShhdmdfc3VpY2lkZSA9IG1lYW4oU3VpY2lkZV9SYXRlKSkgCgoKZ2dwbG90KGF2Z19zdWljaWRlX3llYXJfZ2VybWFueSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX3N1aWNpZGUpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIE92ZXIgVGltZSAtIEdlcm1hbnkiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiU3VpY2lkZSBSYXRlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGF2Z19zdWljaWRlX3llYXJfZ2VybWFueSRZZWFyKSwgbWF4KGF2Z19zdWljaWRlX3llYXJfZ2VybWFueSRZZWFyKSwgYnkgPSAxKSkKYGBgCiMjIyBQbG90IEJhbmtydXB0Y2llcyBSYXRlIEdlcm1hbnkKYGBge3J9CmF2Z19iYW5rX3llYXJfZ2VybWFueSA9IGdlcm1hbnlfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIHN1bW1hcmlzZShhdmdfYmFuayA9IG1lYW4oVmFsdWUpKSAKCgpnZ3Bsb3QoYXZnX2JhbmtfeWVhcl9nZXJtYW55LCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfYmFuaykpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiYmx1ZSIpICsgIAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBiYW5rcnVwdGNpZXMgT3ZlciBUaW1lIC0gR2VybWFueSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJCYW5rcnVwdGNpZXMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX2JhbmtfeWVhcl9nZXJtYW55JFllYXIpLCBtYXgoYXZnX2JhbmtfeWVhcl9nZXJtYW55JFllYXIpLCBieSA9IDEpKQpgYGAKIyMjIFBsb3QgSGFwcGluZXNzIFJhdGUgR2VybWFueQpgYGB7cn0KYXZnX2hhcHBpbmVzc195ZWFyX2dlcm1hbnkgPSBnZXJtYW55X2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX2hhcHB5ID0gbWVhbihMaWZlX2xhZGRlcikpIAoKCmdncGxvdChhdmdfaGFwcGluZXNzX3llYXJfZ2VybWFueSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2hhcHB5KSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEhhcHBpbmVzcyBPdmVyIFRpbWUgLSBHZXJtYW55IiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkhhcHBpbmVzcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfaGFwcGluZXNzX3llYXJfZ2VybWFueSRZZWFyKSwgbWF4KGF2Z19oYXBwaW5lc3NfeWVhcl9nZXJtYW55JFllYXIpLCBieSA9IDEpKQpgYGAKCiMjIyBQbG90IEF2ZXJhZ2UgR0RQIGFuZCBBdmVyYWdlIFN1aWNpZGUgUmF0ZSBvdmVyIHllYXJzIC0gR2VybWFueQpgYGB7cn0KYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55JGF2Z19zdWljaWRlCiMgRmluZGluZyB0aGUgcmF0aW8gZm9yIHNjYWxpbmcgdGhlIHNlY29uZCBheGlzCnJhdGlvIDwtIG1heChhdmdfZ2RwX3llYXJfZ2VybWFueSRhdmdfZ2RwKSAvIG1heChhdmdfc3VpY2lkZV95ZWFyX2dlcm1hbnkkYXZnX3N1aWNpZGUpCgojIENyZWF0aW5nIHRoZSBiYXNlIHBsb3QKZ2dwbG90KCkgKwogICMgQWRkaW5nIHRoZSBiYXIgcGxvdCBmb3IgR0RQCiAgZ2VvbV9saW5lKGRhdGEgPSBhdmdfZ2RwX3llYXJfZ2VybWFueSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2dkcCksIHNpemUgPSAwLjUpICsKICAjIEFkZGluZyB0aGUgbGluZSBwbG90IGZvciBBdmVyYWdlIEhhcHBpbmVzcwogIGdlb21fbGluZShkYXRhID0gYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55LCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfc3VpY2lkZSAqIHJhdGlvKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDAuNSkgKwogICMgRW5oYW5jaW5nIHRoZSBwbG90CiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEdEUCBhbmQgU3VpY2lkZSBSYXRlIE92ZXIgVGltZSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJBdmVyYWdlIEdEUCIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoc2VjLmF4aXMgPSBzZWNfYXhpcyh+IC4gLyByYXRpbywgbmFtZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYyhhdmdfZ2RwX3llYXJfZ2VybWFueSRZZWFyLCBhdmdfc3VpY2lkZV95ZWFyX2dlcm1hbnkkWWVhcikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChjKGF2Z19nZHBfeWVhcl9nZXJtYW55JFllYXIsIGF2Z19zdWljaWRlX3llYXJfZ2VybWFueSRZZWFyKSksIGJ5ID0gMSkpCmBgYAoKIyMjIFBsb3QgQXZlcmFnZSBIYXBwaW5uZXNzIGFuZCBBdmVyYWdlIFN1aWNpZGUgUmF0ZSBvdmVyIHllYXJzIC0gR2VybWFueQpgYGB7cn0KIyBGaW5kaW5nIHRoZSByYXRpbyBmb3Igc2NhbGluZyB0aGUgc2Vjb25kIGF4aXMKcmF0aW8gPC0gbWF4KGF2Z19oYXBwaW5lc3NfeWVhcl9nZXJtYW55JGF2Z19oYXBweSkgLyBtYXgoYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55JGF2Z19zdWljaWRlKQoKIyBDcmVhdGluZyB0aGUgYmFzZSBwbG90CmdncGxvdCgpICsKICAjIEFkZGluZyB0aGUgYmFyIHBsb3QgZm9yIEdEUAogIGdlb21fbGluZShkYXRhID0gYXZnX2hhcHBpbmVzc195ZWFyX2dlcm1hbnksIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19oYXBweSksIHNpemUgPSAwLjUpICsKICAjIEFkZGluZyB0aGUgbGluZSBwbG90IGZvciBBdmVyYWdlIEhhcHBpbmVzcwogIGdlb21fbGluZShkYXRhID0gYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55LCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfc3VpY2lkZSAqIHJhdGlvKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDAuNSkgKwogICMgRW5oYW5jaW5nIHRoZSBwbG90CiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEhhcHBpbm5lc3MgYW5kIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiQXZlcmFnZSBIYXBwaW5uZXNzIikgKwogIHNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvIHJhdGlvLCBuYW1lID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihjKGF2Z19oYXBwaW5lc3NfeWVhcl9nZXJtYW55JFllYXIsIGF2Z19zdWljaWRlX3llYXJfZ2VybWFueSRZZWFyKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGMoYXZnX2hhcHBpbmVzc195ZWFyX2dlcm1hbnkkWWVhciwgYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55JFllYXIpKSwgYnkgPSAxKSkKCmBgYAojIyMgUGxvdCBBdmVyYWdlIEJhbmtydXB0Y2llcyBhbmQgQXZlcmFnZSBTdWljaWRlIFJhdGUgb3ZlciB5ZWFycwpgYGB7cn0KIyBGaW5kaW5nIHRoZSByYXRpbyBmb3Igc2NhbGluZyB0aGUgc2Vjb25kIGF4aXMKcmF0aW8gPC0gbWF4KGF2Z19iYW5rX3llYXJfZ2VybWFueSRhdmdfYmFuaykgLyBtYXgoYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55JGF2Z19zdWljaWRlKQoKIyBDcmVhdGluZyB0aGUgYmFzZSBwbG90CmdncGxvdCgpICsKICAjIEFkZGluZyB0aGUgYmFyIHBsb3QgZm9yIEdEUAogIGdlb21fbGluZShkYXRhID0gYXZnX2JhbmtfeWVhcl9nZXJtYW55LCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfYmFuayksIHNpemUgPSAwLjUpICsKICAjIEFkZGluZyB0aGUgbGluZSBwbG90IGZvciBBdmVyYWdlIEhhcHBpbmVzcwogIGdlb21fbGluZShkYXRhID0gYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55LCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfc3VpY2lkZSAqIHJhdGlvKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDAuNSkgKwogICMgRW5oYW5jaW5nIHRoZSBwbG90CiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEJhbmtydXB0Y2llcyBhbmQgU3VpY2lkZSBSYXRlIE92ZXIgVGltZSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJBdmVyYWdlIEJhbmtydXB0Y2llcyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoc2VjLmF4aXMgPSBzZWNfYXhpcyh+IC4gLyByYXRpbywgbmFtZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYyhhdmdfYmFua195ZWFyX2dlcm1hbnkkWWVhciwgYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55JFllYXIpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoYyhhdmdfYmFua195ZWFyX2dlcm1hbnkkWWVhciwgYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55JFllYXIpKSwgYnkgPSAxKSkKCmBgYAoKCiMjIEluIGRlcHRoIGFuYWx5c2lzIFNvdXRoIEFmcmljYQojIyMgRGF0YSBwcmVwZXJhdGlvbiBmb3IgU291dGggQWZyaWNhCmBgYHtyfQojIFByZXBhcmUgZGF0YSBmb3Igb25seSBHZXJtYW55ClNBX2RhdGEgPSBkYXRhICU+JSAKICBmaWx0ZXIoQ291bnRyeV9uYW1lID09ICJTb3V0aCBBZnJpY2EiKQpgYGAKCiMjIyBQbG90IEdEUCBTQQpgYGB7cn0KIyBQbG90IFNBIEdEUCBvdmVyIFllYXJzCmF2Z19nZHBfeWVhcl9TQSA9IFNBX2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX2dkcCA9IG1lYW4oR0RQKSkgCgoKCmdncGxvdChhdmdfZ2RwX3llYXJfU0EsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19nZHApKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgR1BEIE92ZXIgVGltZSAtIFNBIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkdEUCIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfZ2RwX3llYXJfU0EkWWVhciksIG1heChhdmdfZ2RwX3llYXJfU0EkWWVhciksIGJ5ID0gMSkpCgpgYGAKIyMjIFBsb3QgU3VpY2lkZSBSYXRlIFNBCmBgYHtyfQphdmdfc3VpY2lkZV95ZWFyX1NBID0gU0FfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIHN1bW1hcmlzZShhdmdfc3VpY2lkZSA9IG1lYW4oU3VpY2lkZV9SYXRlKSkgCgoKZ2dwbG90KGF2Z19zdWljaWRlX3llYXJfU0EsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19zdWljaWRlKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUgLSBTQSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJTdWljaWRlIFJhdGUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX3N1aWNpZGVfeWVhcl9TQSRZZWFyKSwgbWF4KGF2Z19zdWljaWRlX3llYXJfU0EkWWVhciksIGJ5ID0gMSkpCmBgYAoKIyMjIFBsb3QgSGFwcGluZXNzIFJhdGUgU0EKYGBge3J9CmF2Z19oYXBwaW5lc3NfeWVhcl9TQSA9IFNBX2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX2hhcHB5ID0gbWVhbihMaWZlX2xhZGRlcikpIAoKCmdncGxvdChhdmdfaGFwcGluZXNzX3llYXJfU0EsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19oYXBweSkpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiYmx1ZSIpICsgIAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBIYXBwaW5lc3MgT3ZlciBUaW1lIC0gU0EiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiSGFwcGluZXNzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGF2Z19oYXBwaW5lc3NfeWVhcl9TQSRZZWFyKSwgbWF4KGF2Z19oYXBwaW5lc3NfeWVhcl9TQSRZZWFyKSwgYnkgPSAxKSkKYGBgCiMjIyBQbG90IEJhbmtydXB0Y2llcyBSYXRlIFNBCmBgYHtyfQphdmdfYmFua195ZWFyX3NhID0gU0FfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIHN1bW1hcmlzZShhdmdfYmFuayA9IG1lYW4oVmFsdWUpKSAKCgpnZ3Bsb3QoYXZnX2JhbmtfeWVhcl9zYSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2JhbmspKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgYmFua3J1cHRjaWVzIE92ZXIgVGltZSAtIFNBIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkJhbmtydXB0Y2llcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfYmFua195ZWFyX3NhJFllYXIpLCBtYXgoYXZnX2JhbmtfeWVhcl9zYSRZZWFyKSwgYnkgPSAxKSkKYGBgCgojIyMgUGxvdCBBdmVyYWdlIEdEUCBhbmQgQXZlcmFnZSBTdWljaWRlIFJhdGUgb3ZlciB5ZWFycyAtIFNBCmBgYHtyfQojIEZpbmRpbmcgdGhlIHJhdGlvIGZvciBzY2FsaW5nIHRoZSBzZWNvbmQgYXhpcwpyYXRpbyA8LSBtYXgoYXZnX2dkcF95ZWFyX1NBJGF2Z19nZHApIC8gbWF4KGF2Z19zdWljaWRlX3llYXJfU0EkYXZnX3N1aWNpZGUpCgojIENyZWF0aW5nIHRoZSBiYXNlIHBsb3QKZ2dwbG90KCkgKwogICMgQWRkaW5nIHRoZSBiYXIgcGxvdCBmb3IgR0RQCiAgZ2VvbV9saW5lKGRhdGEgPSBhdmdfZ2RwX3llYXJfU0EsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19nZHApLCBzaXplID0gMC41KSArCiAgIyBBZGRpbmcgdGhlIGxpbmUgcGxvdCBmb3IgQXZlcmFnZSBIYXBwaW5lc3MKICBnZW9tX2xpbmUoZGF0YSA9IGF2Z19zdWljaWRlX3llYXJfU0EsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19zdWljaWRlICogcmF0aW8pLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMC41KSArCiAgIyBFbmhhbmNpbmcgdGhlIHBsb3QKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgR0RQIGFuZCBTdWljaWRlIFJhdGUgT3ZlciBUaW1lIC0gU0EiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiQXZlcmFnZSBHRFAiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXMofiAuIC8gcmF0aW8sIG5hbWUgPSAiQXZlcmFnZSBTdWljaWRlIFJhdGUiKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGMoYXZnX2dkcF95ZWFyX1NBJFllYXIsIGF2Z19zdWljaWRlX3llYXJfU0EkWWVhcikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChjKGF2Z19nZHBfeWVhcl9TQSRZZWFyLCBhdmdfc3VpY2lkZV95ZWFyX1NBJFllYXIpKSwgYnkgPSAxKSkKYGBgCiMjIyBQbG90IEF2ZXJhZ2UgQmFua3J1cHRjaWVzIGFuZCBBdmVyYWdlIFN1aWNpZGUgUmF0ZSBvdmVyIHllYXJzCmBgYHtyfQojIEZpbmRpbmcgdGhlIHJhdGlvIGZvciBzY2FsaW5nIHRoZSBzZWNvbmQgYXhpcwpyYXRpbyA8LSBtYXgoYXZnX2JhbmtfeWVhcl9zYSRhdmdfYmFuaykgLyBtYXgoYXZnX3N1aWNpZGVfeWVhcl9TQSRhdmdfc3VpY2lkZSkKCiMgQ3JlYXRpbmcgdGhlIGJhc2UgcGxvdApnZ3Bsb3QoKSArCiAgIyBBZGRpbmcgdGhlIGJhciBwbG90IGZvciBHRFAKICBnZW9tX2xpbmUoZGF0YSA9IGF2Z19iYW5rX3llYXJfc2EsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19iYW5rKSwgc2l6ZSA9IDAuNSkgKwogICMgQWRkaW5nIHRoZSBsaW5lIHBsb3QgZm9yIEF2ZXJhZ2UgSGFwcGluZXNzCiAgZ2VvbV9saW5lKGRhdGEgPSBhdmdfc3VpY2lkZV95ZWFyX1NBLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfc3VpY2lkZSAqIHJhdGlvKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDAuNSkgKwogICMgRW5oYW5jaW5nIHRoZSBwbG90CiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEJhbmtydXB0Y2llcyBhbmQgU3VpY2lkZSBSYXRlIE92ZXIgVGltZSAtIFNBIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkF2ZXJhZ2UgQmFua3J1cHRjaWVzIikgKwogIHNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvIHJhdGlvLCBuYW1lID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihjKGF2Z19iYW5rX3llYXJfc2EkWWVhciwgYXZnX3N1aWNpZGVfeWVhcl9TQSRZZWFyKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGMoYXZnX2JhbmtfeWVhcl9zYSRZZWFyLCBhdmdfc3VpY2lkZV95ZWFyX1NBJFllYXIpKSwgYnkgPSAxKSkKYGBgCiMjIyBQbG90IEF2ZXJhZ2UgSGFwcGlubmVzcyBhbmQgQXZlcmFnZSBTdWljaWRlIFJhdGUgb3ZlciB5ZWFycyAtIFNBCmBgYHtyfQojIEZpbmRpbmcgdGhlIHJhdGlvIGZvciBzY2FsaW5nIHRoZSBzZWNvbmQgYXhpcwpyYXRpbyA8LSBtYXgoYXZnX2hhcHBpbmVzc195ZWFyX1NBJGF2Z19oYXBweSkgLyBtYXgoYXZnX3N1aWNpZGVfeWVhcl9TQSRhdmdfc3VpY2lkZSkKCiMgQ3JlYXRpbmcgdGhlIGJhc2UgcGxvdApnZ3Bsb3QoKSArCiAgIyBBZGRpbmcgdGhlIGJhciBwbG90IGZvciBHRFAKICBnZW9tX2xpbmUoZGF0YSA9IGF2Z19oYXBwaW5lc3NfeWVhcl9TQSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2hhcHB5KSwgc2l6ZSA9IDAuNSkgKwogICMgQWRkaW5nIHRoZSBsaW5lIHBsb3QgZm9yIEF2ZXJhZ2UgSGFwcGluZXNzCiAgZ2VvbV9saW5lKGRhdGEgPSBhdmdfc3VpY2lkZV95ZWFyX1NBLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfc3VpY2lkZSAqIHJhdGlvKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDAuNSkgKwogICMgRW5oYW5jaW5nIHRoZSBwbG90CiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEhhcHBpbm5lc3MgYW5kIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUgLSBTQSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJBdmVyYWdlIEhhcHBpbm5lc3MiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXMofiAuIC8gcmF0aW8sIG5hbWUgPSAiQXZlcmFnZSBTdWljaWRlIFJhdGUiKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGMoYXZnX2hhcHBpbmVzc195ZWFyX1NBJFllYXIsIGF2Z19zdWljaWRlX3llYXJfU0EkWWVhcikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChjKGF2Z19oYXBwaW5lc3NfeWVhcl9TQSRZZWFyLCBhdmdfc3VpY2lkZV95ZWFyX1NBJFllYXIpKSwgYnkgPSAxKSkKYGBgCiMgQ29uY2x1c2lvbiBhbmQgU3VtbWFyeQoKVGhpcyBwcm9qZWN0IHByb3ZpZGVkIGEgZmFzY2luYXRpbmcgb3Bwb3J0dW5pdHkgdG8gZGVsdmUgaW50byBhbiB1bmZhbWlsaWFyIHRvcGljLCBhcHBseWluZyB0aGVvcmV0aWNhbCBtZXRob2RzIGxlYXJuZWQgaW4gY2xhc3MgdG8gYSBwcmFjdGljYWwsIHJlYWwtd29ybGQgcHJvamVjdC4gV2UgcGVyZm9ybWVkIGFuIGluLWRlcHRoIGV4cGxvcmF0aW9uIHVzaW5nIGZvdXIgZGlzdGluY3QgZGF0YXNldHM6IFN1aWNpZGUgUmF0ZSwgR0RQIHBlciBDYXBpdGEsIEJhbmtydXB0Y2llcywgYW5kIEhhcHBpbmVzcyBJbmRleC4gVGhlIHllYXJzIHdlcmUgc3Bhbm5pbmcgZnJvbSAyMDExIHRvIDIwMTkuIE91ciBpbml0aWFsIGFwcHJvYWNoIGludm9sdmVkIGFuYWx5emluZyBlYWNoIGRhdGFzZXQgaW5kZXBlbmRlbnRseSB0byB1bmRlcnN0YW5kIGl0cyBjb21wb3NpdGlvbiBhbmQgY29uZHVjdGluZyBwcmVsaW1pbmFyeSBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzLiBUaGlzIGluY2x1ZGVkIHRhc2tzIHN1Y2ggYXMgY2FsY3VsYXRpbmcgYW5kIHBsb3R0aW5nIHRoZSBhdmVyYWdlIGFubnVhbCB2YWx1ZXMgZm9yIGVhY2ggZGF0YXNldCBhY3Jvc3MgdGhlIGdsb2JlLgoKRm9sbG93aW5nIHRoaXMgZm91bmRhdGlvbmFsIGFuYWx5c2lzLCB3ZSBwcm9ncmVzc2VkIHRvIHRoZSBkYXRhIHdyYW5nbGluZyBwaGFzZS4gV2Ugc3VjY2Vzc2Z1bGx5IG1lcmdlZCB0aGUgZm91ciBkYXRhc2V0cy4gVGhlIHJlc3VsdGFudCBjb21iaW5lZCBkYXRhc2V0ICBpbmNsdWRlZCBkYXRhIGZyb20gMTkgY291bnRyaWVzLCBwcm92aWRpbmcgYSAgYmFzaXMgZm9yIGZ1cnRoZXIgYW5hbHlzaXMuIEluIHRoZSBhbmFseXRpY2FsIHBoYXNlLCB3ZSB3YW50ZWQgdG8gdW5jb3ZlciBhbnkgcG90ZW50aWFsIGNvcnJlbGF0aW9ucyB3aXRoaW4gdGhlIGRhdGEgc2V0IG9mIHRoZXNlIDE5IGNvdW50cmllcy4gT3VyIGVmZm9ydHMgdG8gaWRlbnRpZnkgc2lnbmlmaWNhbnQgY29ycmVsYXRpb25zIGFtb25nIHRoZSBkYXRhc2V0cyB3ZXJlIHVuc3VjY2Vzc2Z1bC4KClRvIGdhaW4gZGVlcGVyIGluc2lnaHRzLCB3ZSBuYXJyb3dlZCBvdXIgZm9jdXMgdG8gdHdvIHNwZWNpZmljIGNvdW50cmllczogR2VybWFueSBhbmQgU291dGggQWZyaWNhLiBGb3IgZWFjaCBjb3VudHJ5LCB3ZSBjb25kdWN0ZWQgYSBkZXRhaWxlZCBleHBsb3JhdGlvbiBvZiB0aGVpciBkYXRhLCBwbG90dGluZyB0cmVuZHMgb3ZlciB0aGUgeWVhcnMgYW5kIHNlYXJjaGluZyBmb3IgYW55IGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMgd2l0aGluIGVhY2ggbmF0aW9uYWwgY29udGV4dC4gT3VyIGFuYWx5c2lzIGRpZCBub3QgcmV2ZWFsIGFueSBzaWduaWZpY2FudCBjb3JyZWxhdGlvbnMuCgojIFBvc3NpYmxlIEltcHJvdm1lbnRzCgpHaXZlbiB0aGUgYWJzZW5jZSBvZiBjb3JyZWxhdGlvbnMgaW4gb3VyIGluaXRpYWwgYW5hbHlzZXMsIHdlIHJlY29nbml6ZWQgdGhlIG5lY2Vzc2l0eSB0byB3aWRlbiB0aGUgZGF0YXNldCB0byBlbmhhbmNlIG91ciBzdHVkeS4gUG90ZW50aWFsIGZvciBleHBhbmRpbmcgb3VyIGRhdGFzZXQgaW5jbHVkZSBpbmNvcnBvcmF0aW5nIGFkZGl0aW9uYWwgdmFyaWFibGVzIHN1Y2ggYXMgYWxjb2hvbCBhbmQgZHJ1ZyB1c2FnZSwgdW5lbXBsb3ltZW50IHJhdGVzLCBhbmQgc3Vuc2hpbmUgaG91cnMgaW4gdGhlIGNvdW50cmllcyBzdHVkaWVkLiBBZGRpdGlvbmFsbHksIHRyYW5zaXRpb25pbmcgZnJvbSBhbiBhbm51YWwgdG8gYSBtb250aGx5IGRhdGEgb3ZlcnZpZXcgbWlnaHQgYnJpbmcgc29tZSBiZW5lZml0IGluIGV4cGxvcmluZyB0cmVuZHMgYW5kIGNvcnJlbGF0aW9ucyB0aGF0IHdlcmUgbm90IHZpc2libGUgaW4gdGhlIHllYXJseSBkYXRhLgoKRnVydGhlcm1vcmUsIHRvIGVuaGFuY2UgdGhlIHF1YWxpdHkgYW5kIGRlcHRoIG9mIG91ciBhbmFseXNpcywgZm9jdXNpbmcgb24gbW9yZSBncmFudWxhciBkZXRhaWxzIGNvdWxkIHByb3ZpZGUgc2lnbmlmaWNhbnQgaW5zaWdodHMsIHBhcnRpY3VsYXJseSBieSBleGFtaW5pbmcgdmFyaW91cyBzb2Npby1lY29ub21pYyBhbmQgcG9saXRpY2FsIGZhY3RvcnMgdGhhdCBpbmZsdWVuY2UgY291bnRyeS1zcGVjaWZpYyBiZWhhdmlvcnMuIEluY29ycG9yYXRpbmcgYWRkaXRpb25hbCB2YXJpYWJsZXMgc3VjaCBhcyBwb2xpdGljYWwgc3RhYmlsaXR5LCBzb2NpYWwgY29uZmxpY3RzLCBhbmQgc3BlY2lmaWMgY3VsdHVyYWwgY29uc3RydWN0cyBjb3VsZCBlbnJpY2ggb3VyIHVuZGVyc3RhbmRpbmcgb2YgdGhlIGNvcnJlbGF0aW9ucyBvciBsYWNrIHRoZXJlb2YgaW4gdGhlIGRhdGEuIFRoZXNlIGZhY3RvcnMgb2Z0ZW4gaGF2ZSBwcm9mb3VuZCBpbXBhY3RzIG9uIGVjb25vbWljIGNvbmRpdGlvbnMsIGhhcHBpbmVzcyBpbmRpY2VzLCBhbmQgc29jaWFsIGlzc3VlcyBsaWtlIHN1aWNpZGUgcmF0ZXMgYW5kIGJhbmtydXB0Y3ksIHByb3ZpZGluZyBhIG1vcmUgbnVhbmNlZCBhbmQgY29tcHJlaGVuc2l2ZSBmcmFtZXdvcmsgZm9yIGFuYWx5c2lzLgoKSWYgZ2l2ZW4gdGhlIG9wcG9ydHVuaXR5IHRvIHJldmlzaXQgdGhpcyBwcm9qZWN0IGZyb20gdGhlIGJlZ2lubmluZywgd2Ugd291bGQgaW50ZWdyYXRlIHRoZXNlIGJyb2FkZXIgc29jaW8tcG9saXRpY2FsIHZhcmlhYmxlcyBmcm9tIHRoZSBzdGFydCwgYWxsb3dpbmcgZm9yIGEgbW9yZSB0aG9yb3VnaCBpbml0aWFsIGRhdGEgY29sbGVjdGlvbiBwaGFzZS4gVGhpcyBhcHByb2FjaCB3b3VsZCBlbmFibGUgdXMgdG8gY2FwdHVyZSBhIHdpZGVyIHNwZWN0cnVtIG9mIGluZmx1ZW5jZXMsIHBvdGVudGlhbGx5IHJldmVhbGluZyBoaWRkZW4gcGF0dGVybnMgYW5kIGNvcnJlbGF0aW9ucyB0aGF0IHdlcmUgbm90IGV2aWRlbnQgaW4gb3VyIHByZXZpb3VzIGFuYWx5c2lzLiBNb3Jlb3ZlciwgZW1wbG95aW5nIGFkdmFuY2VkIHN0YXRpc3RpY2FsIG1ldGhvZHMgb3IgbWFjaGluZSBsZWFybmluZyB0ZWNobmlxdWVzIGNvdWxkIGZ1cnRoZXIgYWlkIGluIGlkZW50aWZ5aW5nIGNvbXBsZXggaW50ZXJhY3Rpb25zIGJldHdlZW4gdmFyaWFibGVzLgoKQ29udGludWluZyB0aGlzIHByb2plY3QsIG91ciBuZXh0IHN0ZXBzIHdvdWxkIGludm9sdmUgZXhwYW5kaW5nIG91ciBkYXRhc2V0IHRvIGluY2x1ZGUgdGhlc2UgYWRkaXRpb25hbCBzb2Npby1wb2xpdGljYWwgZmFjdG9ycyBhbmQgYXBwbHlpbmcgbW9yZSBzb3BoaXN0aWNhdGVkIGFuYWx5dGljYWwgdGVjaG5pcXVlcy4gVGhpcyBjb3VsZCBpbnZvbHZlIHRpbWUtc2VyaWVzIGFuYWx5c2lzIGZvciB0cmVuZCBkZXRlY3Rpb24gb3IgY2x1c3RlciBhbmFseXNpcyB0byBpZGVudGlmeSBzaW1pbGFyIGJlaGF2aW9yYWwgcGF0dGVybnMgYWNyb3NzIGRpZmZlcmVudCBjb3VudHJpZXMuIEJ5IGRvaW5nIHNvLCB3ZSBhaW0gdG8gYnVpbGQgYSByaWNoZXIgYW5hbHl0aWNhbCBtb2RlbCB0aGF0IGNhbiBtb3JlIGFjY3VyYXRlbHkgcmVmbGVjdCB0aGUgaW50cmljYXRlIHJlYWxpdGllcyBpbmZsdWVuY2luZyB0aGVzZSBjcml0aWNhbCBzb2NpZXRhbCBpbmRpY2F0b3JzLg==